理解wait、notify、notifyAll

API介紹

//喚醒在此對象監視器上等待的單個線程
void notify()

//喚醒在此對象監視器上等待的所有線程
void notifyAll()

//導致當前的線程等待,直到其他線程調用此對象的notify( ) 方法或 notifyAll( ) 方法
void wait( )

//導致當前的線程等待,直到其他線程調用此對象的notify() 方法或 notifyAll() 方法,或者指定的時間過完。
void wait(long timeout)

//導致當前的線程等待,直到其他線程調用此對象的notify( ) 方法或 notifyAll( ) 方法,或者其他線程打斷了當前線程,或者指定的時間過完。
void wait(long timeout, int nanos)

注意到有個對象監視器的概念

對象監視器是什麼
監視器monitor:可以把它理解爲一種排他性機制,可以用來實現鎖。

同步塊的實現使用了monitor.enter和monitor.exit指令,而同步方法則是依靠方法修飾符上的ACC_SYNCHRONIZED來完成的;其本質是對一個對象的監視器進行獲取
在這裏插入圖片描述
任何線程想要持有Object的鎖,都要嘗試獲取Object的監視器Monitor,如果獲取成功,就持有了該對象的鎖;如果獲取失敗,就進入到同步隊列;當monitor.Exit後,就釋放該對象的鎖,釋放鎖時會喚醒同步隊列等待的線程,他們會嘗試獲取監視器。

鎖住了一個對象,就是獲得對象相關聯的監視器

wait、notify、notifyAll 這三者的使用都必要持有對象的鎖才能執行

Demo

public class Demo {
    private static Object object = new Object();

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        for (int i = 0; i <4 ; i++) {
            int finalI = i;
            new Thread( ()->{
                synchronized (object) {
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(finalI);
                }
            }).start();
        }
        Thread.sleep(3000);
        synchronized (object){
            object.notify();
        }
    }
}
0

結果:輸出0 ,其他線程在等待喚醒。和預想中的一樣,notify只是喚醒其中一個該對象監視器等待的線程

	.......
            object.notifyAll();
   .......

把notify()改成notifyAll()

3
2
1
0

notifyAll:喚醒在此對象監視器上等待的所有線程

參考文章
Java併發-對象監視器
經典解釋監視器和對象鎖

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章