Kirish
Shunday qilib, biz bilamizki, Java-da mavzular bor, ular haqida " Siz Java-ni mavzu bilan buzolmaydi: I qism - mavzular " sharhida o'qishingiz mumkin . Bir vaqtning o'zida ishni bajarish uchun iplar kerak. Shuning uchun, iplar qandaydir tarzda bir-biri bilan o'zaro ta'sir qilish ehtimoli juda katta. Keling, bu qanday sodir bo'lishini va bizda qanday asosiy nazorat borligini aniqlaymiz.Yo'l bering
Thread.yield() usuli sirli va kamdan-kam qo'llaniladi. Internetda uning tavsifining ko'plab variantlari mavjud. Ba'zilar o'zlarining ustuvorliklarini hisobga olgan holda ip pastga siljiydigan iplarning qandaydir navbati haqida yozadilar. Kimdir ish zarrachasi o'z holatini ishlaydigandan ishga tushirilishiga o'zgartirishi haqida yozadi (garchi bu statuslarga bo'linish yo'q va Java ularni ajratmaydi). Lekin, aslida, hamma narsa ancha noma'lum va ma'lum ma'noda oddiyroq. Usul hujjatlari mavzusida " JDK-6416721: (spec thread) Fix Thread.yield() javadocyield
" xatosi mavjud . Agar siz uni o'qigan bo'lsangiz, aslida bu usul faqat Java ish rejasini tuzuvchiga ushbu mavzuni bajarish uchun kamroq vaqt berilishi mumkinligi haqida ba'zi tavsiyalarni bildirishi aniq . Ammo aslida nima sodir bo'ladi, rejalashtiruvchi tavsiyani eshitadimi yoki umuman nima qilishi JVM va operatsion tizimni amalga oshirishga bog'liq. Yoki ba'zi boshqa omillar tufayli. Barcha chalkashliklar, ehtimol, Java tilini ishlab chiqish jarayonida multithreadingni qayta ko'rib chiqish bilan bog'liq. Batafsil " Java Thread.yield() ga qisqacha kirish " sharhida o'qishingiz mumkin. yield
Kutish - uxlab qolgan ip
Ishlash paytida ip uxlab qolishi mumkin. Bu boshqa iplar bilan o'zaro aloqaning eng oddiy turi. Java virtual mashinasi o'rnatilgan, Java kodi bajariladigan operatsion tizimda Thread Scheduler deb nomlangan o'z ish jadvali mavjud. Qaysi ipni qachon o'tkazishni o'zi hal qiladi. Dasturchi ushbu rejalashtiruvchi bilan to'g'ridan-to'g'ri Java kodidan o'zaro aloqada bo'lolmaydi, lekin u JVM orqali rejalashtiruvchidan mavzuni bir muddat to'xtatib turishini va "uyqu rejimiga o'tkazishni" so'rashi mumkin. Batafsil " Thread.sleep() " va " Multithreading qanday ishlaydi " maqolalarida o'qishingiz mumkin . Bundan tashqari, Windows OS da iplar qanday ishlashini bilib olishingiz mumkin: " Windows Threadning ichki qismi ". Endi biz buni o'z ko'zimiz bilan ko'ramiz. Quyidagi kodni faylga saqlaymizHelloWorldApp.java
:
class HelloWorldApp {
public static void main(String []args) {
Runnable task = () -> {
try {
int secToWait = 1000 * 60;
Thread.currentThread().sleep(secToWait);
System.out.println("Waked up");
} catch (InterruptedException e) {
e.printStackTrace();
}
};
Thread thread = new Thread(task);
thread.start();
}
}
Ko'rib turganingizdek, bizda 60 soniya kutadigan vazifa bor, shundan so'ng dastur tugaydi. Biz kompilyatsiya qilamiz javac HelloWorldApp.java
va ishga tushiramiz java HelloWorldApp
. Alohida oynada ishga tushirish yaxshidir. Masalan, Windows-da bu shunday bo'ladi: start java HelloWorldApp
. jps buyrug'idan foydalanib, biz jarayonning PID-ni topamiz va dan foydalanib mavzular ro'yxatini ochamiz jvisualvm --openpid pidПроцесса
: Ko'rib turganingizdek, bizning ipimiz Uyqu holatiga kirdi. Aslida, joriy ipni uxlashni yanada chiroyli qilish mumkin:
try {
TimeUnit.SECONDS.sleep(60);
System.out.println("Waked up");
} catch (InterruptedException e) {
e.printStackTrace();
}
Ehtimol, biz hamma joyda ishlov berishimizni payqadingizmi InterruptedException
? Keling, nima uchun ekanligini tushunaylik.
Mavzuni uzish yoki Thread.interrupt
Gap shundaki, ip tushida kutayotganda, kimdir bu kutishni to'xtatmoqchi bo'lishi mumkin. Bunday holda, biz bunday istisno bilan shug'ullanamiz. Bu usulThread.stop
eskirgan deb e'lon qilinganidan keyin amalga oshirildi, ya'ni. eskirgan va foydalanish uchun istalmagan. Buning sababi, usul chaqirilganda, stop
ip oddiygina "o'ldirilgan", bu juda oldindan aytib bo'lmaydigan edi. Oqim qachon to'xtatilishini bila olmadik, ma'lumotlarning izchilligiga kafolat bera olmadik. Tasavvur qiling-a, siz faylga ma'lumot yozyapsiz va keyin oqim yo'q qilinadi. Shuning uchun, biz oqimni o'ldirmaslik, balki uni to'xtatish kerakligi haqida xabar berish mantiqan to'g'ri keladi, deb qaror qildik. Bunga qanday munosabatda bo'lish oqimning o'ziga bog'liq. Batafsil ma'lumotni Oracle'ning " Thred.stop nima uchun eskirgan? " Keling, bir misolni ko'rib chiqaylik:
public static void main(String []args) {
Runnable task = () -> {
try {
TimeUnit.SECONDS.sleep(60);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
};
Thread thread = new Thread(task);
thread.start();
thread.interrupt();
}
Ushbu misolda biz 60 soniya kutmaymiz, lekin darhol "Uzilgan" ni chop qilamiz. Buning sababi, biz ipning usulini chaqirdik interrupt
. Ushbu usul "uzilish holati deb ataladigan ichki bayroq" ni o'rnatadi. Ya'ni, har bir ip to'g'ridan-to'g'ri kirish imkoni bo'lmagan ichki bayroqqa ega. Ammo bizda ushbu bayroq bilan ishlashning mahalliy usullari mavjud. Lekin bu yagona yo'l emas. Ip bajarilish jarayonida bo'lishi mumkin, biror narsani kutmasdan, balki shunchaki harakatlarni bajaradi. Ammo bu ular o'z ishining ma'lum bir nuqtasida uni yakunlashni xohlashlarini ta'minlashi mumkin. Masalan:
public static void main(String []args) {
Runnable task = () -> {
while(!Thread.currentThread().isInterrupted()) {
//Do some work
}
System.out.println("Finished");
};
Thread thread = new Thread(task);
thread.start();
thread.interrupt();
}
Yuqoridagi misolda siz while
ip tashqi tomondan uzilib qolguncha tsiklning ishlashini ko'rishingiz mumkin. IsInterrupted bayrog'i haqida bilish kerak bo'lgan muhim narsa shundaki, agar biz uni ushlasak InterruptedException
, bayroq isInterrupted
qayta o'rnatiladi va keyin isInterrupted
u noto'g'ri bo'ladi. Bundan tashqari, Thread klassi uchun statik usul mavjud bo'lib, u faqat joriy mavzuga tegishli - Thread.interrupted() , lekin bu usul bayroqni noto'g'ri holatga qaytaradi! Batafsil ma'lumotni " Mavzuning uzilishi " bo'limida o'qishingiz mumkin .
Qo‘shilish — boshqa mavzu tugashini kutmoqda
Kutishning eng oddiy turi boshqa mavzu tugashini kutishdir.public static void main(String []args) throws InterruptedException {
Runnable task = () -> {
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
System.out.println("Interrupted");
}
};
Thread thread = new Thread(task);
thread.start();
thread.join();
System.out.println("Finished");
}
Ushbu misolda yangi ip 5 soniya davomida uxlaydi. Shu bilan birga, asosiy ip uxlab yotgan ip uyg'onguncha va o'z ishini tugatguncha kutadi. Agar siz JVisualVM orqali qarasangiz, ipning holati quyidagicha ko'rinadi: Monitoring vositalari tufayli ip bilan nima sodir bo'layotganini ko'rishingiz mumkin. Usul join
juda oddiy, chunki bu oddiygina java kodi bo'lgan usul bo'lib, u wait
chaqirilgan ip tirik bo'lganda bajariladi. Ip o'lgandan keyin (tugatishda), kutish tugaydi. Bu usulning butun sehridir join
. Shuning uchun, keling, eng qiziqarli qismga o'tamiz.
Kontseptsiya monitori
Multithreadingda Monitor kabi narsa mavjud. Umuman olganda, monitor so'zi lotin tilidan "nazoratchi" yoki "nazoratchi" deb tarjima qilingan. Ushbu maqola doirasida biz mohiyatni eslab qolishga harakat qilamiz va istaganlar uchun batafsil ma'lumot uchun havolalardan materialga sho'ng'ishingizni so'rayman. Sayohatimizni Java tili spetsifikatsiyasidan, ya'ni JLS bilan boshlaylik: " 17.1. Sinxronizatsiya ". Unda quyidagilar aytiladi: Ma'lum bo'lishicha, Java mavzular o'rtasida sinxronizatsiya qilish uchun "Monitor" deb nomlangan ma'lum bir mexanizmdan foydalanadi. Har bir ob'ekt u bilan bog'langan monitorga ega va iplar uni qulflashi yoki qulfini ochishi mumkin. Keyinchalik, biz Oracle veb-saytida o'quv qo'llanmasini topamiz: " Ichki qulflar va sinxronizatsiya ". Ushbu qo'llanmada Java-da sinxronizatsiya ichki blokirovka yoki monitor blokirovkasi deb nomlanuvchi ichki ob'ekt atrofida qurilganligi tushuntiriladi. Ko'pincha bunday qulf oddiygina "monitor" deb ataladi. Yana shuni ko'ramizki, Java-dagi har bir ob'ekt u bilan bog'langan ichki qulfga ega. Siz " Java - ichki qulflar va sinxronizatsiya " ni o'qishingiz mumkin. Keyinchalik, Java-dagi ob'ektni monitor bilan qanday bog'lash mumkinligini tushunish muhimdir. Java-dagi har bir ob'ekt sarlavhaga ega - dasturchi uchun koddan mavjud bo'lmagan, lekin virtual mashina ob'ektlar bilan to'g'ri ishlashi uchun zarur bo'lgan ichki metama'lumotlarning bir turi. Ob'ekt sarlavhasi quyidagicha ko'rinadigan MarkWord ni o'z ichiga oladi:https://edu.netbeans.org/contrib/slides/java-overview-and-java-se6.pdf
public class HelloWorld{
public static void main(String []args){
Object object = new Object();
synchronized(object) {
System.out.println("Hello World");
}
}
}
Shunday qilib, kalit so'zdan foydalanib, synchronized
joriy ip (bu kod satrlari bajarilgan) ob'ekt bilan bog'langan monitordan foydalanishga harakat qiladi object
va "qulflash" yoki "monitorni qo'lga olish" (ikkinchi variant hatto afzalroqdir). Agar monitor uchun hech qanday qarama-qarshilik bo'lmasa (ya'ni, boshqa hech kim bir xil ob'ektda sinxronlashni xohlamasa), Java "biased locking" deb nomlangan optimallashtirishni amalga oshirishga harakat qilishi mumkin. Mark Word-dagi ob'ektning sarlavhasida mos teg va monitor qaysi ipga biriktirilganligi yozuvi bo'ladi. Bu monitorni suratga olishda ortiqcha xarajatlarni kamaytiradi. Agar monitor allaqachon boshqa ipga ulangan bo'lsa, unda bu qulflash etarli emas. JVM keyingi qulflash turiga o'tadi - asosiy qulflash. U solishtirish va almashtirish (CAS) operatsiyalaridan foydalanadi. Shu bilan birga, Mark Word-dagi sarlavha endi Mark Word-ning o'zini saqlamaydi, lekin uni saqlash uchun havola + teg o'zgartiriladi, shunda JVM biz asosiy qulflashdan foydalanayotganimizni tushunadi. Agar bir nechta iplarning monitorida kelishmovchilik bo'lsa (biri monitorni ushlab oldi, ikkinchisi monitorning chiqishini kutmoqda), u holda Mark Word-dagi teg o'zgaradi va Mark Word monitorga havolani saqlashni boshlaydi. ob'ekt - JVM ning ba'zi ichki ob'ekti. JEPda aytilganidek, bu holda ushbu ob'ektni saqlash uchun Native Heap xotira maydonida bo'sh joy talab qilinadi. Ushbu ichki ob'ektning saqlash joyiga havola Mark Word ob'ektida joylashgan bo'ladi. Shunday qilib, biz ko'rib turganimizdek, monitor haqiqatan ham umumiy resurslarga bir nechta oqimlarning kirishini sinxronlashtirishni ta'minlaydigan mexanizmdir. JVM o'rtasida almashinadigan ushbu mexanizmning bir nechta ilovalari mavjud. Shuning uchun, oddiylik uchun, monitor haqida gapirganda, biz aslida qulflar haqida gapiramiz.
Sinxronlashtirilgan va qulf bilan kutish
Monitor kontseptsiyasi, biz ilgari ko'rganimizdek, "sinxronizatsiya bloki" tushunchasi bilan chambarchas bog'liq (yoki uni tanqidiy qism deb ham atashadi). Keling, bir misolni ko'rib chiqaylik:public static void main(String[] args) throws InterruptedException {
Object lock = new Object();
Runnable task = () -> {
synchronized (lock) {
System.out.println("thread");
}
};
Thread th1 = new Thread(task);
th1.start();
synchronized (lock) {
for (int i = 0; i < 8; i++) {
Thread.currentThread().sleep(1000);
System.out.print(" " + i);
}
System.out.println(" ...");
}
}
Bu erda asosiy ip birinchi navbatda vazifani yangi ipga yuboradi, so'ngra darhol qulfni "qo'lga oladi" va u bilan uzoq operatsiyani bajaradi (8 soniya). Bu vaqt davomida vazifa uning bajarilishi uchun blokga kira olmaydi synchronized
, chunki qulf allaqachon band. Agar ip qulfni ololmasa, u uni monitorda kutadi. Qabul qilishi bilanoq u ijroni davom ettiradi. Ip monitordan chiqib ketganda, u qulfni chiqaradi. JVisualVM da u quyidagicha ko'rinadi: Ko'rib turganingizdek, JVisualVM dagi holat "Monitor" deb ataladi, chunki ip bloklangan va monitorni egallay olmaydi. Siz koddagi ipning holatini ham bilib olishingiz mumkin, ammo bu holat nomi JVisualVM shartlariga mos kelmaydi, garchi ular o'xshash bo'lsa ham. Bunday holda, th1.getState()
tsikl BLOCKED nifor
qaytaradi , chunki Loop ishlayotganda, monitor ip bilan band bo'ladi va ip bloklanadi va qulf qaytarilmaguncha ishlashni davom ettira olmaydi. Sinxronizatsiya bloklariga qo'shimcha ravishda, butun usul ham sinxronlashtirilishi mumkin. Masalan, sinfdan bir usul : lock
main
th1
HashTable
public synchronized int size() {
return count;
}
Bir birlik vaqt ichida bu usul faqat bitta ip tomonidan bajariladi. Lekin bizga qulf kerak, to'g'rimi? Ha, menga kerak. Ob'ekt usullari bo'lsa, qulf bo'ladi this
. Ushbu mavzu bo'yicha qiziqarli munozara mavjud: " Sinxronlashtirilgan blok o'rniga Sinxronlashtirilgan usuldan foydalanishning afzalligi bormi? ". Agar usul statik bo'lsa, u holda blokirovka bo'lmaydi this
(chunki statik usul uchun bo'lishi mumkin emas this
), balki sinf ob'ekti (Masalan, Integer.class
).
Kuting va monitorda kuting. Ogohlantirish va bildirishning barcha usullari
Threadda monitorga ulangan boshqa kutish usuli mavjud.sleep
va dan farqli o'laroq join
, uni shunchaki chaqirib bo'lmaydi. Va uning ismi wait
. Usul wait
biz monitorida kutmoqchi bo'lgan ob'ektda bajariladi. Keling, misolni ko'rib chiqaylik:
public static void main(String []args) throws InterruptedException {
Object lock = new Object();
// task будет ждать, пока его не оповестят через lock
Runnable task = () -> {
synchronized(lock) {
try {
lock.wait();
} catch(InterruptedException e) {
System.out.println("interrupted");
}
}
// После оповещения нас мы будем ждать, пока сможем взять лок
System.out.println("thread");
};
Thread taskThread = new Thread(task);
taskThread.start();
// Ждём и после этого забираем себе лок, оповещаем и отдаём лок
Thread.currentThread().sleep(3000);
System.out.println("main");
synchronized(lock) {
lock.notify();
}
}
JVisualVM-da u quyidagicha ko'rinadi: Bu qanday ishlashini tushunish uchun usullar ga murojaat qilishini yodda tutishingiz kerak . Mavzu bilan bog'liq usullarning mavjudligi g'alati tuyuladi . Lekin bu erda javob yotadi. Esda tutganimizdek, Java-dagi har bir ob'ekt sarlavhaga ega. Sarlavhada turli xil xizmat ma'lumotlari, jumladan, monitor haqidagi ma'lumotlar - blokirovka holati haqidagi ma'lumotlar mavjud. Va biz eslayotganimizdek, har bir ob'ekt (ya'ni, har bir misol) ichki blokirovka deb ataladigan ichki JVM ob'ekti bilan bog'langan, u ham monitor deb ataladi. Yuqoridagi misolda vazifa biz bilan bog'langan monitorda sinxronizatsiya blokiga kirishimizni tasvirlaydi . Agar ushbu monitorda qulfni olish mumkin bo'lsa, u holda . Ushbu vazifani bajaruvchi ip monitorni chiqaradi , lekin monitörde bildirishnomani kutayotgan iplar navbatiga qo'shiladi . Ushbu iplar navbati WAIT-SET deb ataladi, bu esa mohiyatni to'g'riroq aks ettiradi. Bu navbatdan ko'ra ko'proq to'plam. Ip vazifa vazifasi bilan yangi ip yaratadi, uni ishga tushiradi va 3 soniya kutadi. Bu yuqori ehtimollik bilan yangi ipga ipdan oldin qulfni ushlab , monitorda navbatda turishga imkon beradi. Shundan so'ng, ipning o'zi sinxronizatsiya blokiga kiradi va monitorda ip haqida xabar beradi. Bildirishnoma yuborilgandan so'ng, ip monitorni chiqaradi va yangi oqim (ilgari kutilgan) monitorning chiqarilishini kutgandan so'ng ishlashni davom ettiradi. Xabarnomani faqat bitta mavzuga ( ) yoki navbatdagi barcha mavzularga bir vaqtning o'zida yuborish mumkin ( ). Batafsil " Java'da notify() va notifyAll() o'rtasidagi farq " bo'limida o'qishingiz mumkin . Shuni ta'kidlash kerakki, bildirishnomalar tartibi JVMni amalga oshirishga bog'liq. Batafsil ma'lumotni " Ochlikni notify and notifyall bilan qanday hal qilish mumkin? ". Sinxronizatsiya ob'ektni ko'rsatmasdan amalga oshirilishi mumkin. Buni kodning alohida bo'limi emas, balki butun usul sinxronlashtirilganda amalga oshirilishi mumkin. Masalan, statik usullar uchun blok sinf ob'ekti bo'ladi (orqali orqali olinadi ): wait
notify
java.lang.Object
Object
lock
wait
lock
lock
main
main
main
lock
main
lock
lock
notify
notifyAll
.class
public static synchronized void printA() {
System.out.println("A");
}
public static void printB() {
synchronized(HelloWorld.class) {
System.out.println("B");
}
}
Qulflarni ishlatish nuqtai nazaridan ikkala usul ham bir xil. Agar usul statik bo'lmasa, u holda sinxronizatsiya joriy bo'yicha amalga oshiriladi instance
, ya'ni this
. Aytgancha, avvalroq biz ushbu usul yordamida getState
ipning holatini olishingiz mumkinligini aytdik. wait
Demak, monitor tomonidan navbatga qoʻyilgan ip mavjud, agar usul kutish vaqti chegarasini koʻrsatsa, holat KUTISH yoki TIMED_WAITING boʻladi .
Ipning hayot aylanishi
Ko'rib turganimizdek, oqim hayot davomida o'z maqomini o'zgartiradi. Aslida, bu o'zgarishlar ipning hayot aylanishidir. Mavzu endigina yaratilganda, u YANGI maqomiga ega bo'ladi. Bu holatda, u hali boshlanmagan va Java Thread Scheduler yangi mavzu haqida hali hech narsa bilmaydi. Tarmoq rejalashtiruvchisi mavzu haqida bilishi uchun sizthread.start()
. Keyin ip RUNNABLE holatiga o'tadi. Internetda Runnable va Running holatlari ajratilgan ko'plab noto'g'ri sxemalar mavjud. Lekin bu xato, chunki... Java "ishlash uchun tayyor" va "ishlash" holatini farqlamaydi. Agar ip jonli, lekin faol bo'lmasa (Runnable emas), u ikkita holatdan birida bo'ladi:
- BLOCKED - himoyalangan bo'limga kirishni kutadi, ya'ni. blokga
synchonized
. - WAITING - shart asosida boshqa ipni kutadi. Agar shart to'g'ri bo'lsa, ipni rejalashtiruvchi ipni boshlaydi.
getState
. isAlive
Mavzular, shuningdek , agar ip tugatilmasa, true qiymatini qaytaradigan usulga ega .
LockSupport va to'xtash joyi
Java 1.6 dan boshlab LockSupport deb nomlangan qiziqarli mexanizm mavjud edi . Bu sinf "ruxsat" yoki ruxsatni undan foydalanadigan har bir oqim bilan bog'laydi.park
Qo'ng'iroq paytida xuddi shu ruxsatni egallagan ruxsat mavjud bo'lsa, usul chaqiruvi darhol qaytariladi. Aks holda u bloklanadi. Usulni chaqirish, unpark
agar u allaqachon mavjud bo'lmasa, ruxsatni beradi. Faqat 1 ta ruxsatnoma mavjud Java API da LockSupport
ma'lum Semaphore
. Keling, oddiy misolni ko'rib chiqaylik:
import java.util.concurrent.Semaphore;
public class HelloWorldApp{
public static void main(String[] args) {
Semaphore semaphore = new Semaphore(0);
try {
semaphore.acquire();
} catch (InterruptedException e) {
// Просим разрешение и ждём, пока не получим его
e.printStackTrace();
}
System.out.println("Hello, World!");
}
}
Bu kod abadiy kutadi, chunki semaforda endi 0 ruxsatnomasi bor. Va kod bilan chaqirilganda acquire
(ya'ni, ruxsat so'raganda), ip ruxsat olguncha kutadi. Biz kutayotganimiz sababli, biz uni qayta ishlashga majburmiz InterruptedException
. Qizig'i shundaki, semafor alohida ip holatini amalga oshiradi. Agar biz JVisualVM ga qarasak, bizning davlatimiz Wait emas, balki Park ekanligini ko'ramiz. Keling, yana bir misolni ko'rib chiqaylik:
public static void main(String[] args) throws InterruptedException {
Runnable task = () -> {
//Запаркуем текущий поток
System.err.println("Will be Parked");
LockSupport.park();
// Как только нас распаркуют - начнём действовать
System.err.println("Unparked");
};
Thread th = new Thread(task);
th.start();
Thread.currentThread().sleep(2000);
System.err.println("Thread state: " + th.getState());
LockSupport.unpark(th);
Thread.currentThread().sleep(2000);
}
Mavzu holati KUTILADI, lekin JVisualVM wait
dan synchronized
va park
dan farq qiladi LockSupport
. Nima uchun bu juda muhim LockSupport
? Keling, yana Java API-ga qaytaylik va Thread State WAITING ni ko'rib chiqaylik . Ko'rib turganingizdek, unga kirishning faqat uchta usuli bor. 2 yo'l - bu wait
va join
. Va uchinchisi LockSupport
. Java-dagi qulflar bir xil printsiplar asosida qurilgan LockSupport
va yuqori darajadagi vositalarni ifodalaydi. Keling, bittasini ishlatishga harakat qilaylik. Keling, masalan, quyidagi manzilni ko'rib chiqaylik ReentrantLock
:
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class HelloWorld{
public static void main(String []args) throws InterruptedException {
Lock lock = new ReentrantLock();
Runnable task = () -> {
lock.lock();
System.out.println("Thread");
lock.unlock();
};
lock.lock();
Thread th = new Thread(task);
th.start();
System.out.println("main");
Thread.currentThread().sleep(2000);
lock.unlock();
}
}
Oldingi misollarda bo'lgani kabi, bu erda hamma narsa oddiy. lock
kimdir resurs chiqarishini kutadi. main
Agar biz JVisualVM ni ko'rib chiqsak, biz ip unga qulfni bermaguncha yangi ip to'xtab turishini ko'ramiz . Qulflar haqida ko'proq ma'lumotni bu yerda o'qishingiz mumkin: " Java 8 da ko'p tarmoqli dasturlash. Ikkinchi qism. O'zgaruvchan ob'ektlarga kirishni sinxronlash " va " Java Lock API. Foydalanish nazariyasi va misoli ." Qulflarni amalga oshirishni yaxshiroq tushunish uchun " Phaser Class " sharhida Phazer haqida o'qish foydali bo'ladi . Turli xil sinxronizatorlar haqida gapiradigan bo'lsak, siz Habré-dagi " Java.util.concurrent.* Sinxronizatorlar ma'lumotnomasi " maqolasini o'qishingiz kerak .
GO TO FULL VERSION