JavaRush /Блоги Java /Random-TG /Идоракунии ҷараёни. Калимаи калидӣ ва усули yield().

Идоракунии ҷараёни. Калимаи калидӣ ва усули yield().

Дар гурӯҳ нашр шудааст
Салом! Мо омӯзиши чанд риштаро идома дода истодаем ва имрӯз мо бо як калимаи нави калидӣ - усули volatile ва yield() шинос мешавем. Биёед бифаҳмем, ки ин чист :)

Калимаи калидӣ

Ҳангоми сохтани замимаҳои бисёр ришта мо метавонем бо ду мушкилоти ҷиддӣ рӯ ба рӯ шавем. Аввалан, ҳангоми кори як замимаи бисёрқабата, риштаҳои гуногун метавонанд қиматҳои тағирёбандаҳоро кэш кунанд (мо дар ин бора дар лексияи "Истифодаи ноустувор" бештар сӯҳбат хоҳем кард ). Мумкин аст, ки як ришта арзиши тағирёбандаро тағир диҳад, аммо дуввум ин тағиротро надид, зеро он бо нусхаи кэшшудаи тағирёбанда кор мекард. Табиист, ки оқибатҳо метавонанд ҷиддӣ бошанд. Тасаввур кунед, ки ин на танҳо як навъ "тағйирёбанда", балки барои мисол, тавозуни корти бонкии шумо, ки ногаҳон ба таври тасодуфӣ ба пешу пас ҷаҳида оғоз кард :) На он қадар гуворо, дуруст? Дуюм, дар Java, амалиёти хондан ва навиштанро дар ҳама гуна майдонҳо, ба истиснои longва doubleатомӣ. Атомӣ чист? Хуб, масалан, агар шумо арзиши як тағирёбандаро дар як ришта тағир диҳед intва дар риштаи дигар арзиши ин тағирёбандаро хонед, шумо ё арзиши кӯҳнаи онро мегиред ё арзиши навро, ки пас аз тағир додани он пайдо шуд риштаи 1. Дар он ҷо ягон "имконоти мобайнӣ" пайдо намешавад Шояд. Аммо, ин бо longва doubleкор намекунад . Чаро? Зеро он кросс-платформа аст. Оё шумо дар хотир доред, ки чӣ тавр мо дар сатҳи аввал гуфта будем, ки принсипи Java "як бор навишта мешавад, дар ҳама ҷо кор мекунад"? Ин кросс-платформа аст. Яъне, барномаи Java дар платформаҳои тамоман дигар кор мекунад. Масалан, дар системаҳои оператсионии Windows, versionҳои гуногуни Linux ё MacOS ва дар ҳама ҷо ин барнома устувор кор мекунад. longва double- примитивҳои аз ҳама "вазнин" дар Java: вазнашон 64 бит. Ва баъзе платформаҳои 32-битӣ атомии хондан ва навиштани тағирёбандаҳои 64-битиро иҷро намекунанд. Чунин тағирёбандаҳо дар ду амал хонда ва навишта мешаванд. Аввалан, 32 битҳои аввал ба тағирёбанда навишта мешаванд, баъд 32 бит. Мувофиқи ин, дар ин мавридҳо мушкилот пайдо шуданаш мумкин аст. Як ришта арзиши 64-битро ба тағирёбанда менависадХ, ва вай ин корро «дар ду қадам» мекунад. Дар айни замон, риштаи дуюм кӯшиш мекунад, ки арзиши ин тағирёбандаро бихонад ва онро дуруст дар мобайн иҷро мекунад, вақте ки 32 битҳои аввал аллакай навишта шудаанд, вале дуюмашон ҳанӯз навишта нашудаанд. Дар натиҷа, он арзиши фосилавӣ ва нодурустро мехонад ва хатогӣ ба амал меояд. Масалан, агар дар чунин платформа мо кӯшиш кунем, ки рақамро ба тағирёбанда нависем - 9223372036854775809 - он 64 битро ишғол мекунад. In binary form it will look like this: 100000000000000000000000000000000000000000000000000000000000000001 The first thread will start writing this number to a variable, and will first write the first 32 bits: 1000000000000000000000000000 00000 and then the second 32: 00000000000000000000000000000001 And a second thread can wedge into this gap and арзиши фосилавии тағирёбандаро хонед - 1000000000000000000000000000000000, 32 битҳои аввал, ки аллакай навишта шудаанд. Дар системаи даҳӣ ин адад ба 2147483648 баробар аст. Яъне мо танҳо мехостем рақами 9223372036854775809-ро ба тағирёбанда нависем, аммо аз сабаби он ки ин амалиёт дар баъзе платформаҳо атомӣ нест, мо рақами “чап”-ро гирифтем 2147483648 , ки ба мо лозим нест, аз кучо. ва маълум нест, ки он ба кори барнома чй гуна таъсир мерасонад. Риштаи дуюм танҳо арзиши тағирёбандаро пеш аз навиштани он хонд, яъне 32 битҳои аввалро дид, аммо 32 битҳои дуюмро не. Ин мушкилот, албатта, дирӯз ба вуҷуд наомадаанд ва дар Java онҳо танҳо бо истифода аз як калимаи калидӣ ҳал карда мешаванд - volatile . Агар мо дар барномаи худ ягон тағирёбандаро бо калимаи ноустувор эълон кунем...
public class Main {

   public volatile long x = 2222222222222222222L;

   public static void main(String[] args) {

   }
}
... ин маънои онро дорад:
  1. Он ҳамеша ба таври атомӣ хонда ва навишта мешавад. Ҳатто агар он 64-бит doubleё long.
  2. Мошини Java онро кэш намекунад. Ҳамин тавр, вазъияте, ки 10 ришта бо нусхаҳои маҳаллии худ кор мекунад, истисно карда мешавад.
Ин аст, ки ду мушкилоти хеле ҷиддӣ дар як калима ҳал карда мешаванд :)

Усули yield ().

Мо аллакай бисёр усулҳои синфро дида баромадем Thread, аммо як чизи муҳиме ҳаст, ки барои шумо нав хоҳад буд. Ин усули yield() аст . Аз инглисӣ ҳамчун "додан" тарҷума шудааст. Ва ин маҳз ҳамон чизест, ки усул кор мекунад! Идоракунии ҷараёни.  Калимаи калидӣ ва усули yield() - 2Вақте ки мо усули ҳосилхезиро дар ришта меномем, он воқеан ба риштаҳои дигар мегӯяд: "Хуб, бачаҳо, ман саросема нестам, бинобар ин, агар барои касе аз шумо гирифтани вақти CPU муҳим бошад, онро бигиред, ман таъҷилӣ нест." Ин як мисоли оддии он аст, ки чӣ тавр кор мекунад:
public class ThreadExample extends Thread {

   public ThreadExample() {
       this.start();
   }

   public void run() {

       System.out.println(Thread.currentThread().getName() + "give way to others");
       Thread.yield();
       System.out.println(Thread.currentThread().getName() + " has finished executing.");
   }

   public static void main(String[] args) {
       new ThreadExample();
       new ThreadExample();
       new ThreadExample();
   }
}
Мо пай дар пай се ришта - Thread-0, Thread-1ва Thread-2. Thread-0аввал сар мешавад ва дархол ба дигарон рох медихад. Пас аз он оғоз меёбад Thread-1, ва инчунин роҳ медиҳад. Пас аз он, он оғоз меёбад Thread-2, ки он ҳам пасттар аст. Мо дигар ришта надорем ва пас аз он ки Thread-2риштаи охирин аз ҷои худ даст кашид, нақшакаш назар мекунад: «Пас, дигар риштаҳои нав нест, мо дар навбат кӣ ҳастем? Кӣ охирин бор пештар ҷои худро дод Thread-2? Ман фикр мекунам он буд Thread-1? Хуб, бигзор он иҷро шавад." Thread-1кори худро то охир ичро мекунад, баъд аз он планкаш риштаро координация мекунад: «Хуб, ришта-1 ба охир расид. Оё мо ягон каси дигар дорем? ” Дар навбат Thread-0 мавҷуд аст: он фавран пеш аз Thread-1 ҷои худро дод. Холо кор ба сари у расида, то охир ичро карда мешавад. Пас аз он нақшасоз ҳамоҳангсозии риштаҳоро анҷом медиҳад: "Хуб, Thread-2, шумо ба риштаҳои дигар роҳ додед, онҳо аллакай кор кардаанд. Шумо охирин касе будед, ки роҳ додед, акнун навбати шумост.” Пас аз ин, Thread-2 ба анҷом мерасад. Натиҷаи консол чунин хоҳад буд: Thread-0 ба дигарон ҷой медиҳад Thread-1 ба дигарон ҷой медиҳад Thread-2 ба дигарон медиҳад Thread-1 иҷроишро анҷом дод. Thread-0 иҷроишро анҷом дод. Thread-2 иҷроишро анҷом дод. Барномасози ришта, албатта, метавонад риштаҳоро бо тартиби дигар иҷро кунад (масалан, 2-1-0 ба ҷои 0-1-2), аммо принсип як аст.

Пеш аз қоидаҳо рӯй медиҳад

Охирин чизе, ки мо имрӯз ба он муроҷиат хоҳем кард, ин принсипҳои " пеш аз рӯй медиҳад " аст. Тавре ки шумо аллакай медонед, дар Java, қисми зиёди кори ҷудо кардани вақт ва захираҳо ба риштаҳо барои анҷом додани вазифаҳои онҳо аз ҷониби нақшаи ришта анҷом дода мешавад. Инчунин, шумо зиёда аз як маротиба дидаед, ки чӣ гуна риштаҳо бо тартиби худсарона иҷро мешаванд ва аксар вақт пешгӯии он ғайриимкон аст. Ва дар маҷмӯъ, пас аз барномасозии "пайвандӣ", ки мо қаблан анҷом дода будем, чанд ришта ба як чизи тасодуфӣ монанд аст. Тавре ки шумо аллакай дидед, пешрафти як барномаи бисёрҷабҳаро метавон бо истифода аз маҷмӯи тамоми усулҳо идора кард. Аммо илова бар ин, дар Java multithreading боз як "ҷазираи устуворӣ" мавҷуд аст - 4 қоида бо номи " рӯй медиҳад-пеш ". Айнан аз забони англисӣ ин ҳамчун "пеш аз рӯй медиҳад" ё "пеш аз он рӯй медиҳад" тарҷума шудааст. Маънои ин қоидаҳоро фаҳмидан хеле осон аст. Тасаввур кунед, ки мо ду ришта дорем - Aва B. Ҳар яке аз ин риштаҳо метавонанд амалҳо 1ва 2. Ва ҳангоме ки дар ҳар як қоида мо мегӯем " А рӯй медиҳад-пеш аз В " ин маънои онро дорад, ки ҳамаи тағиротҳои ришта Aпеш аз амалиёт 1ва тағироте, ки ин амалиёт ба он овардааст, Bдар вақти анҷом додани амалиёт ба ришта намоён аст 2ва пас аз анҷом додани амалиёт. Ҳар яке аз ин қоидаҳо кафолат медиҳад, ки ҳангоми навиштани барномаи бисёрсабҳа баъзе рӯйдодҳо 100% пеш аз дигарон рӯй медиҳанд ва ришта Bдар вақти амалиёт 2ҳамеша аз тағироте, ки ришта Аҳангоми амалиёт анҷом додааст, огоҳ хоҳад буд. 1. Биёед ба онҳо назар андозем.

Қоидаи 1.

Баровардани мутекс пеш аз он ки риштаи дигар ҳамон мониторро ба даст орад, рух медиҳад. Хуб, дар ин ҷо ҳама чиз равшан ба назар мерасад. Агар мутекси an object ё синф бо як ришта ба даст оварда шавад, масалан, ришта А, риштаи дигар (thread B) дар як вақт онро ба даст оварда наметавонад. Шумо бояд то он даме, ки mutex озод карда шавад, интизор шавед.

Қоидаи 2.

Thread.start() Ин пеш аз усул рӯй медиҳад Thread.run(). Ҳеҷ чиз мураккаб ҳам нест. Шумо аллакай медонед: барои он ки code дар дохor метод иҷро шавад run(), шумо бояд усулро дар ришта даъват кунед start(). Ин аз они аст, на худи усул run()! Ин қоида кафолат медиҳад, ки Thread.start()арзишҳои ҳама тағирёбандаҳои пеш аз иҷро муқарраршуда дар дохor усуле, ки ба иҷро оғоз кардаанд, намоён хоҳанд шуд run().

Қоидаи 3.

Анҷоми усул run() пеш аз баромадани усул сурат мегирад join(). Биёед ба ду ҷараёнамон баргардем - Ава B. Мо усулро join()тавре меномем, ки ришта Bбояд то анҷоми Aкораш интизор шавад. Ин маънои онро дорад, ки усули run()an objectи А, бешубҳа, то охир кор хоҳад кард. Ва ҳама тағирот дар маълумоте, ки дар усули run()ришта ба амал меоянд A, дар ришта Bҳангоми интизории анҷомёбӣ Aва худ ба кор шурӯъ мекунанд, комилан намоён хоҳанд шуд.

Қоидаи 4.

Навиштан ба тағирёбандаи тағйирёбанда пеш аз хондан аз ҳамон тағирёбанда сурат мегирад . Бо истифода аз калимаи калидӣ, мо воқеан ҳамеша арзиши ҷориро мегирем. Хатто дар мавриди longва double, проблемахое, ки пештар бо онхо сухан рафт. Тавре ки шумо аллакай фаҳмед, тағирот дар баъзе риштаҳо на ҳама вақт ба риштаҳои дигар намоён мешаванд. Аммо, албатта, аксар вақт ҳолатҳое ҳастанд, ки чунин рафтори барнома ба мо мувофиқат намекунад. Фарз мекунем, ки мо ба тағирёбанда дар ришта арзиш таъин кардем A:
int z;.

z= 555;
Агар риштаи мо Bарзиши тағирёбандаро zба консол чоп мекард, он метавонад ба осонӣ 0-ро чоп кунад, зеро вай дар бораи арзиши ба он таъиншуда хабар надорад. Ҳамин тавр, Қоидаи 4 ба мо кафолат медиҳад: агар шумо тағирёбандаро zноустувор эълон кунед, тағирот ба арзишҳои он дар як ришта ҳамеша дар риштаи дигар намоён хоҳад буд. Агар мо калимаи ноустуворро ба рамзи қаблӣ илова кунем...
volatile int z;.

z= 555;
...вазъияте, ки ҷараён B0 ба консол мебарорад, истисно карда мешавад. Навиштан ба тағирёбандаҳои тағйирёбанда пеш аз хондан аз онҳо сурат мегирад.
Шарҳҳо
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION