JavaRush /Java блогы /Random-KK /Тақырыпты синхрондау. Java тіліндегі синхрондалған операт...

Тақырыпты синхрондау. Java тіліндегі синхрондалған оператор

Топта жарияланған
Сәлеметсіз бе! Бүгін біз көп ағынды бағдарламалау мүмкіндіктерін қарастыруды және ағынды синхрондау туралы сөйлесуді жалғастырамыз.
Жіпті синхрондау.  Оператор синхрондалған - 1
«Синхрондау» дегеніміз не? Бағдарламалау аймағынан тыс бұл екі құрылғының немесе бағдарламаның бірге жұмыс істеуіне мүмкіндік беретін орнатудың қандай да бір түріне жатады. Мысалы, смартфон мен компьютерді Google есептік жазбасымен, ал веб-сайттағы жеке есептік жазбаны әлеуметтік желілердегі тіркелгілермен синхрондауға болады, олар арқылы кіру үшін. Ағынды синхрондау ұқсас мағынаға ие: бұл ағындардың бір-бірімен әрекеттесу жолын орнату. Алдыңғы лекцияларда біздің жіптер бір-бірінен бөлек өмір сүріп, жұмыс істеді. Біреуі бірдеңені санады, екіншісі ұйықтап жатты, үшіншісі консольде бірдеңені көрсетіп тұрды, бірақ олар бір-бірімен араласпады. Нақты бағдарламаларда мұндай жағдайлар сирек кездеседі. Бірнеше ағындар белсенді жұмыс істей алады, мысалы, деректердің бірдей жиынтығымен және ондағы бір нәрсені өзгерте алады. Бұл проблемаларды тудырады. Бірнеше ағындар мәтінді мәтіндік файл немесе консоль сияқты бір орынға жазып жатыр деп елестетіңіз. Бұл жағдайда бұл файл немесе консоль ортақ ресурсқа айналады. Жіптер бір-бірінің бар екендігі туралы білмейді, сондықтан олар ағынды жоспарлаушы оларға бөлетін уақыт ішінде басқара алатын барлық нәрсені жазады. Курстың жақында өткен лекциясында бізде мұның не әкелетіні туралы мысал болды, оны еске түсірейік: Мұның Тақырыпты синхрондау.  Синхрондалған оператор - 2себебі ағындардың ортақ ресурспен, консольмен, әрекеттерді бір-бірімен үйлестірмей жұмыс істегенінде жатыр. Егер ағынды жоспарлаушы Thread-1-ге уақыт бөлсе, ол барлығын консольге бірден жазады. Басқа ағындардың не жаза алғаны немесе жаза алмағаны маңызды емес. Нәтижесі, көріп отырғаныңыздай, қайғылы. Сондықтан көп ағынды бағдарламалауда арнайы мутекс концепциясы енгізілді (ағылшын тілінен «mutex», «mutual exclusion» - «mutual exclusion») . Мутекстің мақсаты - белгілі бір уақытта нысанға тек бір ағынның қол жеткізуі үшін механизмді қамтамасыз ету. Егер Thread-1 А нысанының мутексін алған болса, басқа ағындар ондағы ештеңені өзгерту үшін оған қол жеткізе алмайды. А нысанының мутексі шығарылғанша, қалған ағындар күтуге мәжбүр болады. Өмірден алынған мысал: сіз және тағы 10 бейтаныс адам тренингке қатысып жатыр деп елестетіңіз. Сіз кезекпен ойыңызды айтып, бір нәрсені талқылауыңыз керек. Бірақ, сіз бір-біріңізді бірінші рет көріп отырғандықтан, үнемі бір-біріңізге кедергі келтірмеу үшін және «сөйлейтін доп» ережесін қолданасыз: тек бір адам сөйлей алады - допты ұстаған адам. оның қолдары. Осылайша талқылау адекватты және нәтижелі болып шығады. Сонымен, мутекс, мәні бойынша, осындай шар. Егер нысанның мутексі бір ағынның қолында болса, басқа ағындар нысанға қол жеткізе алмайды. Мутекс жасау үшін ештеңе істеудің қажеті жоқ: ол қазірдің өзінде сыныпқа салынған Object, яғни Java-дағы әрбір нысанда бар.

Синхрондалған оператор Java тілінде қалай жұмыс істейді

Жаңа кілт сөзбен танысайық - синхрондалған . Ол біздің codeтың белгілі бір бөлігін белгілейді. Егер code блогы синхрондалған кілт сөзбен белгіленсе, бұл блокты бір уақытта тек бір ағынмен орындауға болатындығын білдіреді. Синхрондау әртүрлі жолдармен жүзеге асырылуы мүмкін. Мысалы, тұтас синхрондалған әдісті жасаңыз:
public synchronized void doSomething() {

   //...method logic
}
Немесе кейбір нысанда синхрондау жүзеге асырылатын code блогын жазыңыз:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
Мағынасы қарапайым. Егер бір ағын синхрондалған сөзбен белгіленген code блогына кірсе, ол an objectінің мутексін лезде алады және сол блокқа немесе әдіске кіруге тырысатын барлық басқа ағындар алдыңғы ағын жұмысын аяқтағанша күтуге мәжбүр болады және монитор. Жіпті синхрондау.  Синхрондалған оператор - 3Айтпақшы! Курстық дәрістерде сіз синхрондалған мысалдарды көрдіңіз, бірақ олар басқаша көрінді:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
Тақырып сіз үшін жаңа, әрине, алдымен синтаксиспен шатасу болады. Сондықтан, кейінірек жазу әдістерінде шатастырмау үшін бірден есте сақтаңыз. Бұл екі жазу әдісі бірдей нәрсені білдіреді:
public void swap() {

   synchronized (this)
   {
       //...method logic
   }
}


public synchronized void swap() {

   }
}
Бірінші жағдайда әдісті енгізгеннен кейін бірден codeтың синхрондалған блогын жасайсыз. thisОл нысан арқылы , яғни ағымдағы нысан арқылы синхрондалады . Ал екінші мысалда сіз бүкіл әдіске синхрондалған сөзді қойдыңыз. Синхрондау жүзеге асырылатын кез келген нысанды нақты көрсетудің қажеті жоқ. Бүкіл әдіс сөзбен белгіленгеннен кейін бұл әдіс класстың барлық нысандары үшін автоматты түрде синхрондалады. Қай әдіс жақсырақ екенін талқылауға кіріспейік. Әзірге өзіңізге ұнайтын нәрсені таңдаңыз :) Ең бастысы есте сақтаңыз: оның ішіндегі барлық логика бір уақытта бір ағынмен орындалғанда ғана әдісті синхрондалған деп жариялауға болады. Мысалы, бұл жағдайда doSomething()әдісті синхрондау қате болады:
public class Main {

   private Object obj = new Object();

   public void doSomething() {

       //...some logic available to all threads

       synchronized (obj) {

           //logic that is only available to one thread at a time
       }
   }
}
Көріп отырғаныңыздай, әдіс бөлігінде синхрондау қажет емес логика бар. Ондағы codeты бір уақытта бірнеше ағынмен орындауға болады және барлық маңызды орындар бөлек синхрондалған блокқа бөлінген. Және бір сәт. Дәрістегі мысалды микроскоппен қарастырайық:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
Назар аударыңыз: синхрондау арқылы жүзеге асырылады this. Яғни, белгілі бір нысан үшін MyClass. Бізде 2 жіп ( Thread-1және Thread-2) және бір ғана нысан бар деп елестетіңіз MyClass myClass. Бұл жағдайда, егер Thread-1әдіс деп шақырылса myClass.swap(), нысанның мутексі бос емес болады және Thread-2оны шақыруға әрекеттенген кезде myClass.swap()ол мутекстің бос болуын күтіп тұрып қалады. Егер бізде 2 ағын және 2 нысан MyClass- myClass1және myClass2- әртүрлі нысандарда болса, біздің ағындар бір уақытта синхрондалған әдістерді оңай орындай алады. Бірінші ағын келесі әрекеттерді орындайды:
myClass1.swap();
Екіншісі:
myClass2.swap();
Бұл жағдайда әдіс ішіндегі синхрондалған кілт сөз swap()бағдарламаның жұмысына әсер етпейді, өйткені синхрондау белгілі бір an objectіде жүзеге асырылады. Ал соңғы жағдайда бізде 2 нысан бар.Сондықтан жіптер бір-біріне қиындық тудырмайды. Өйткені, екі an objectінің 2 түрлі мутексі бар және олардың түсірілуі бір-біріне тәуелді емес.

Статикалық әдістердегі синхронизацияның ерекшеліктері

Бірақ статикалық әдісті синхрондау қажет болса ше?
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

   public static synchronized void swap() {
       String s = name1;
       name1 = name2;
       name2 = s;
   }

}
Бұл жағдайда мутекс ретінде не қызмет ететіні белгісіз. Өйткені, біз әрбір нысанның мутексі бар деп шештік. Бірақ мәселе мынада, статикалық әдісті шақыру үшін MyClass.swap()бізге нысандар қажет емес: әдіс статикалық! Әрі қарай не? :/ Шындығында, бұл мәселеде ешқандай проблема жоқ. Java жасаушылар барлығын шешті :) Егер сыни «көп ағынды» логиканы қамтитын әдіс статикалық болса, синхрондау сынып бойынша жүзеге асырылады. Түсінікті болу үшін жоғарыдағы codeты келесідей қайта жазуға болады:
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

   public static void swap() {

       synchronized (MyClass.class) {
           String s = name1;
           name1 = name2;
           name2 = s;
       }
   }

}
Негізінде, сіз бұл туралы өзіңіз ойлаған болар едіңіз: нысандар жоқ болғандықтан, синхрондау механизмі қандай да бір түрде сыныптардың өздеріне «байланысты» болуы керек. Міне осылай: сыныптар арасында синхрондауға болады.
Пікірлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION