JavaRush /Java blogi /Random-UZ /Mavzuni sinxronlashtirish. Java-da sinxronlashtirilgan op...

Mavzuni sinxronlashtirish. Java-da sinxronlashtirilgan operator

Guruhda nashr etilgan
Salom! Bugun biz ko'p bosqichli dasturlashning xususiyatlarini ko'rib chiqishni davom ettiramiz va iplarni sinxronlashtirish haqida gapiramiz.
Mavzuni sinxronlashtirish.  Operator sinxronlashtirildi - 1
"Sinxronizatsiya" nima? Dasturlash doirasidan tashqarida, bu ikkita qurilma yoki dasturning birgalikda ishlashiga imkon beruvchi qandaydir sozlashni anglatadi. Masalan, smartfon va kompyuter Google hisob qaydnomasi bilan, veb-saytdagi shaxsiy hisob esa ijtimoiy tarmoqlardagi akkauntlardan foydalanib tizimga kirish uchun sinxronlashtirilishi mumkin. Mavzuni sinxronlashtirish xuddi shunday ma'noga ega: bu iplarning bir-biri bilan o'zaro ta'sirini o'rnatish. Oldingi ma'ruzalarda bizning iplarimiz bir-biridan alohida yashagan va ishlagan. Biri nimanidir hisoblardi, ikkinchisi uxlab yotardi, uchinchisi konsolda nimanidir ko'rsatardi, lekin ular bir-birlari bilan aloqa qilmadilar. Haqiqiy dasturlarda bunday holatlar kam uchraydi. Bir nechta iplar, masalan, bir xil ma'lumotlar to'plami bilan faol ishlashi va undagi biror narsani o'zgartirishi mumkin. Bu muammolarni keltirib chiqaradi. Tasavvur qiling-a, bir nechta iplar matnni bir xil joyga, masalan, matn fayli yoki konsolga yozmoqda. Ushbu fayl yoki konsol bu holda umumiy manbaga aylanadi. Mavzular bir-birining mavjudligi haqida bilishmaydi, shuning uchun ular shunchaki mavzu rejalashtiruvchisi ularga ajratgan vaqt ichida boshqarishi mumkin bo'lgan hamma narsani yozadilar. Kursning yaqinda o'tkazilgan ma'ruzasida biz bu nimaga olib kelishi haqida misol keltirdik, keling, buni eslaylik: Mavzuni sinxronlashtirish.  Sinxronlashtirilgan operator - 2Buning sababi shundaki, iplar umumiy resurs, konsol bilan, harakatlarni bir-biri bilan muvofiqlashtirmasdan ishlagan. Agar mavzu rejalashtiruvchisi Thread-1 ga vaqt ajratgan bo'lsa, u darhol hamma narsani konsolga yozadi. Boshqa mavzular allaqachon yozishga muvaffaq bo'lgan yoki yozishga muvaffaq bo'lmagani muhim emas. Natija, ko'rib turganingizdek, halokatli. Shuning uchun, ko'p bosqichli dasturlashda maxsus mutex tushunchasi kiritildi (inglizcha "mutex", "mutual exclusion" - "o'zaro istisno" dan) . Muteksning maqsadi - ma'lum bir vaqtda faqat bitta ipning ob'ektga kirish huquqiga ega bo'lishi uchun mexanizmni ta'minlash. Agar Thread-1 A ob'ektining mutexini olgan bo'lsa, undagi biror narsani o'zgartirish uchun boshqa iplar unga kirish huquqiga ega bo'lmaydi. A ob'ektining mutexi chiqarilgunga qadar, qolgan iplar kutishga majbur bo'ladi. Haqiqiy hayotdan misol: tasavvur qiling-a, siz va yana 10 nafar notanish odam treningda qatnashmoqdasiz. Siz navbatma-navbat fikr bildirishingiz va biror narsani muhokama qilishingiz kerak. Ammo, siz bir-biringizni birinchi marta ko'rayotganingiz uchun, doimiy ravishda bir-biringizga xalaqit bermaslik va janjalga tushmaslik uchun siz "gapirish to'pi" qoidasidan foydalanasiz: faqat bitta odam gapira oladi - to'p bo'lgan odam. uning qo'llari. Shunday qilib, muhokama adekvat va samarali bo'ladi. Demak, mutex, mohiyatiga ko'ra, shunday to'pdir. Agar ob'ektning mutexi bitta ipning qo'lida bo'lsa, boshqa iplar ob'ektga kira olmaydi. Muteks yaratish uchun hech narsa qilishingiz shart emas: u allaqachon sinfga o'rnatilgan Object, ya'ni Java'dagi har bir ob'ektda mavjud.

Sinxronlashtirilgan operator Java-da qanday ishlaydi

Keling, yangi kalit so'z bilan tanishamiz - sinxronlashtirilgan . Bu bizning kodimizning ma'lum bir qismini belgilaydi. Agar kod bloki sinxronlashtirilgan kalit so'z bilan belgilangan bo'lsa, bu blok bir vaqtning o'zida faqat bitta ip tomonidan bajarilishi mumkinligini anglatadi. Sinxronizatsiya turli yo'llar bilan amalga oshirilishi mumkin. Masalan, butun sinxronlashtirilgan usulni yarating:
public synchronized void doSomething() {

   //...method logic
}
Yoki ba'zi bir ob'ektda sinxronizatsiya amalga oshiriladigan kod blokini yozing:
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
       }
   }
}
Ma'nosi oddiy. Agar bitta ip sinxronlashtirilgan so'z bilan belgilangan kod blokiga kirsa, u bir zumda ob'ektning mutexiga ega bo'ladi va bir xil blok yoki usulga kirishga urinayotgan boshqa barcha iplar oldingi ip o'z ishini tugatguncha kutishga majbur bo'ladi. monitor. Mavzuni sinxronlashtirish.  Sinxronlashtirilgan operator - 3Aytmoqchi! Kurs ma'ruzalarida siz sinxronlashtirilgan misollarni ko'rgansiz, ammo ular boshqacha ko'rinishga ega edi:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
Mavzu siz uchun yangi va, albatta, dastlab sintaksis bilan chalkashlik bo'ladi. Shuning uchun, keyinchalik yozish usullarida adashmaslik uchun darhol eslab qoling. Ushbu ikkita yozish usuli bir xil narsani anglatadi:
public void swap() {

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


public synchronized void swap() {

   }
}
Birinchi holda, siz usulga kirganingizdan so'ng darhol sinxronlashtirilgan kod blokini yaratasiz. thisU ob'ekt tomonidan , ya'ni joriy ob'ekt tomonidan sinxronlashtiriladi . Va ikkinchi misolda siz sinxronlashtirilgan so'zni butun usulga qo'yasiz. Endi sinxronizatsiya amalga oshiriladigan ob'ektni aniq ko'rsatishga hojat yo'q. Butun usul so'z bilan belgilangandan so'ng, bu usul avtomatik ravishda sinfning barcha ob'ektlari uchun sinxronlashtiriladi. Keling, qaysi usul yaxshiroq ekanligini muhokama qilmaylik. Hozircha o'zingizga ko'proq yoqqanini tanlang :) Asosiysi esda tuting: siz metodni uning ichidagi barcha mantiq bir vaqtning o'zida bitta ip tomonidan bajarilgandagina sinxronlangan deb e'lon qilishingiz mumkin. Masalan, bu holda doSomething()usulni sinxronlashtirish xato bo'ladi:
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
       }
   }
}
Ko'rib turganingizdek, usulning bir qismi sinxronizatsiya talab qilinmaydigan mantiqni o'z ichiga oladi. Undagi kod bir vaqtning o'zida bir nechta iplar tomonidan bajarilishi mumkin va barcha muhim joylar alohida sinxronlashtirilgan blokga ajratilgan. Va bir daqiqa. Keling, nomlar almashinuvi bilan ma'ruzadagi misolimizni mikroskop ostida ko'rib chiqaylik:
public void swap()
{
   synchronized (this)
   {
       //...method logic
   }
}
Iltimos, diqqat qiling: sinxronizatsiya yordamida amalga oshiriladi this. Ya'ni, ma'lum bir ob'ekt uchun MyClass. Tasavvur qiling, bizda 2 ta ip ( Thread-1va Thread-2) va faqat bitta ob'ekt bor MyClass myClass. Bunday holda, agar Thread-1usul chaqirilsa myClass.swap(), ob'ektning mutexi band bo'ladi va Thread-2siz unga qo'ng'iroq qilmoqchi bo'lganingizda, myClass.swap()mutex bo'sh bo'lishini kutib osilib qoladi. Agar bizda 2 ta ip va 2 ta ob'ekt bo'lsa MyClass- myClass1va myClass2- turli ob'ektlarda, bizning iplarimiz bir vaqtning o'zida sinxronlashtirilgan usullarni osongina bajarishi mumkin. Birinchi mavzu quyidagilarni bajaradi:
myClass1.swap();
Ikkinchisi:
myClass2.swap();
Bunday holda, usul ichidagi sinxronlangan kalit so'z swap()dasturning ishlashiga ta'sir qilmaydi, chunki sinxronizatsiya ma'lum bir ob'ektda amalga oshiriladi. Va oxirgi holatda bizda 2 ta ob'ekt bor.Shuning uchun iplar bir-biriga muammo tug'dirmaydi. Axir, ikkita ob'ektda 2 xil mutex mavjud va ularni qo'lga olish bir-biriga bog'liq emas.

Statik usullarda sinxronlashning xususiyatlari

Ammo statik usulni sinxronlashtirish kerak bo'lsa nima bo'ladi?
class MyClass {
   private static String name1 = "Olya";
   private static String name2 = "Lena";

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

}
Bu holatda mutex sifatida nima xizmat qilishi aniq emas. Axir, biz allaqachon har bir ob'ektning mutexga ega ekanligiga qaror qildik. Ammo muammo shundaki, statik usulni chaqirish uchun MyClass.swap()bizga ob'ektlar kerak emas: usul statik! Va undan keyin nima? :/ Aslida, bu bilan hech qanday muammo yo'q. Java yaratuvchilari hamma narsaga g'amxo'rlik qilishdi :) Agar tanqidiy "ko'p oqimli" mantiqni o'z ichiga olgan usul statik bo'lsa, sinxronizatsiya sinf tomonidan amalga oshiriladi. Aniqlik uchun yuqoridagi kodni quyidagicha qayta yozish mumkin:
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;
       }
   }

}
Asosan, siz buni o'zingiz o'ylab ko'rishingiz mumkin edi: ob'ektlar yo'qligi sababli, sinxronizatsiya mexanizmi qandaydir tarzda sinflarning o'ziga "o'rnatilgan" bo'lishi kerak. Bu shunday: siz sinflar bo'ylab ham sinxronlashtirishingiz mumkin.
Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION