理解此問題先修知識:
synchronized 的含義:
- Java中每一個對象都可以成爲一個監視器(Monitor), 該Monitor由一個鎖(lock), 一個等待隊列(waiting
queue ), 一個入口隊列( entry queue). - 對於一個對象的方法, 如果沒有synchronized關鍵字, 該方法可以被任意數量的線程,在任意時刻調用。
- 對於添加了synchronized關鍵字的方法,任意時刻只能被唯一的一個獲得了對象實例鎖的線程調用。
- synchronized用於實現多線程的同步操作
wait()功用
- wait(), notify(), notifyAll() 和 synchonized 需要搭配使用, 用於線程同步
- wait()總是在一個循環中被調用,掛起當前線程來等待一個條件的成立。 Wait調用會一直等到其他線程調用notifyAll()時才返回。
- 當一個線程在執行synchronized 的方法內部,調用了wait()後, 該線程會釋放該對象的鎖,
然後該線程會被添加到該對象的等待隊列中(waiting queue), 只要該線程在等待隊列中, 就會一直處於閒置狀態, 不會被調度執行。
要注意wait()方法會強迫線程先進行釋放鎖操作,所以在調用wait()時,
該線程必須已經獲得鎖,否則會拋出異常。由於wait()在synchonized的方法內部被執行, 鎖一定已經獲得, 就不會拋出異常了。
notify()的功用
- wait(), notify(), notifyAll() 和 synchonized 需要搭配使用, 用於線程同步
- 當一個線程調用一個對象的notify()方法時, 調度器會從所有處於該對象等待隊列(waiting queue)的線程中取出任意一個線程,
將其添加到入口隊列( entry queue) 中. 然後在入口隊列中的多個線程就會競爭對象的鎖, 得到鎖的線程就可以繼續執行。
如果等待隊列中(waiting queue)沒有線程, notify()方法不會產生任何作用 - notifyAll() 和notify()工作機制一樣, 區別在於notifyAll()會將等待隊列(waiting
queue)中所有的線程都添加到入口隊列中(entry queue) - 注意, notifyAll()比notify()更加常用, 因爲notify()方法只會喚起一個線程,
且無法指定喚醒哪一個線程,所以只有在多個執行相同任務的線程在併發運行時, 我們不關心哪一個線程被喚醒時,纔會使用notify()
正確寫法
// 線程 A 的代碼
synchronized(obj_A)
{
while(!condition){
obj_A.wait();
}
// do something
}
// 線程 B 的代碼
synchronized(obj_A)
{
if(!condition){
// do something ...
condition = true;
obj_A.notify();
}
}
————————————————
版權聲明:本文爲CSDN博主「蕭蕭冷」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/lengxiao1993/article/details/52296220