wait,notify,notifyAll為什麼一定要在Synchronized代碼塊中使用

Object.wait(),

Object.notify(),Object.notifyAll()都是Object的方法,換句話說,就是每個類裡面都有這些方法。

Object.wait():釋放當前對象鎖,釋放CPU資料,並進入等待隊列

Object.notify():喚醒當前對象阻塞隊列裡的任一線程(並不保證喚醒哪一個)

Object.notifyAll():喚醒當前對象阻塞隊列裡的所有線程

為什麼這三個方法要與synchronized一起使用呢?解釋這個問題之前,我們先要了解幾個知識點

每一個對象都有一個與之對應的監視器

每一個監視器裡面都有一個該對象的和一個等待隊列和一個同步隊列

wait()方法的語義有兩個,一是釋放當前對象鎖,另一個是進入

等待隊列,可以看到,這些操作都是與監視器相關的,當然要指定一個監視器(Monitor)才能完成這個操作了(剛好synchronized代碼塊中可以獲取一個對象得監視器)

notify()方法也是一樣的,用來喚醒一個線程,你要去喚醒,首先你得知道他在哪兒,所以必須先找到該對象,也就是獲取該對象的鎖,當獲取到該對象的鎖之後,才能去該對象的對應的等待隊列去喚醒一個線程。值得注意的是,只有當執行喚醒工作的線程離開同步塊,即釋放鎖之後,被喚醒線程才能去競爭鎖。

notifyAll()方法和notify()一樣,只不過是喚醒等待隊列中的所有線程

因wait()而導致阻塞的線程是放在等待隊列中的,因競爭失敗導致的阻塞是放在同步隊列中的,notify()/notifyAll()實質上是把等待隊列中的線程放到同步隊列中去了。

需要注意的是:三個方法都必須在 synchronized 同步關鍵字 所 限 定 的 作 用 域 中 調 用 , 否 則 會 報 錯

java.lang.IllegalMonitorStateException ,意思是因為沒有同步,所以線程對對象鎖的狀態是不確定的,不能調用這些方法。

waity /notify 的原理圖

wait,notify,notifyAll為什麼一定要在Synchronized代碼塊中使用


分享到:


相關文章: