摘要:等待一段時間是否有線程喚醒鎖,如果沒有,超時自動喚醒。隨機喚醒等待隊列中的等待同一個鎖的一個線程,使這個線程退出等待隊列,進入可運行狀態。條件隊列中是處于等待狀態的線程,等待特定條件為真。在一般情況下,總應該調用喚醒所有需要被喚醒的線程。
方法
java.lang.Object
public final native void wait() throws InterruptedException; public final native void wait(long millis, int nanos) throws InterruptedException; public final void wait(long millis) throws InterruptedException { wait(millis, 0); } public final native void notify(); public final native void notifyAll();
wait():使調用該方法的線程釋放鎖,從運行狀態退出,進入等待隊列,直到被喚醒。
wait(long timeout):等待一段時間是否有線程喚醒鎖,如果沒有,超時自動喚醒。
wait(long timeout, int nanos):等待喚醒時間納秒級別。
notify():隨機喚醒等待隊列中的等待同一個鎖的一個線程,使這個線程退出等待隊列,進入可運行狀態。
notifyAll():喚醒所有等待同樣鎖的所有線程,從等待隊列中退出,進入可運行狀態。
注意點在調用wait或者notify之前,必須獲得該對象的對象鎖,即,只能在同步方法中調用;
執行完wait之后釋放對象鎖,所以其他線程可以獲得執行機會,才能喚醒;
執行notify之后,不會立即退出讓wait的線程執行,必須要先把同步塊中的程序執行完,退出同步塊,才會釋放鎖,讓等待線程執行;
notify每次通知一個線程,多次調用通知線程數增加,可將wait線程全部喚醒。
原理每個對象都有個monitor,初始是0,執行完synchronized值就是1。
wait/notify需要在獲得monitor的線程中才可以執行。
所以,wait/notify需要在synchronized中執行。
其中,wait又會釋放掉鎖,破壞掉同步。
跟synchronized關系synchronized代碼塊生成的字節碼,被monitorenter和monitorexit包圍,持有對象的monitor;
線程執行wait/notify方法時,必須持有對象的monitor;
所以,wait/notify方法在synchronized同步塊中執行,就持有了對象的鎖。
互斥和協同Java語言的同步機制在底層實現上只有兩種方式:互斥和協同。
互斥:即synchronized內置鎖。
協同:即內置條件隊列,wait/notify/notifyAll。
條件隊列中是處于等待狀態的線程,等待特定條件為真。每個Java對象都可以作為一個鎖,同樣每個Java對象都可以作為一個條件隊列。通過wait/notify/notifyAll來操作條件隊列。
可以理解為:有一個隊列,o.wait()就push進去,o.notify()就pull出來。
要調用條件隊列的任何一個方法,都必須要獲得對象上的鎖。
線程是用來工作的,不應該處于等待狀態,處于等待狀態的條件隊列中的線程,一定是執行不下去的。
在while中等待while(condition is not true) { lock.wait() }
解釋:兩個消費者線程c1和c2,邏輯都是,判斷資源是否為空,是就wait,否就消費一個;某個時刻,兩個線程都進入等待隊列,然后生產者生產了一個資源,并執行notifyAll,喚醒c1和c2都進入鎖池,c1先獲取鎖,執行完消費掉資源,然后釋放鎖,此時,如果c2獲得鎖,如果是if邏輯,那么就會進入消費代碼,但是資源已經被c1消費掉了,可能拋出異常。如果是while邏輯,則不會進入消費代碼,而是繼續等待。
在一般情況下,總應該調用notifyAll喚醒所有需要被喚醒的線程。可能會喚醒其他一些線程,但這不影響程序的正確性,這些線程醒來之后,會檢查他們正在等待的條件(循環檢測),如果發現條件不滿足,就會繼續等待
顯示鎖和顯示條件隊列顯示鎖:Lock,對應內置鎖synchronized
顯示條件隊列:Condition,對應內置條件隊列,對應方法是await, signal, signalAll
問題notifyAll喚醒所有線程,但不是所有線程都能執行,必須要等待對象鎖被釋放,獲取鎖之后才能執行。可以說,notifyAll讓線程進入鎖池。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70909.html
摘要:在這個等待通知機制中,我們需要考慮以下四個要素。何時等待線程要求的條件不滿足就等待。是會隨機地通知等待隊列中的一個線程,而會通知等待隊列中的所有線程。 由上一篇文章你應該已經知道,在 破壞占用且等待條件 的時候,如果轉出賬本和轉入賬本不滿足同時在文件架上這個條件,就用死循環的方式來循環等待,核心代碼如下: // 一次性申請轉出賬戶和轉入賬戶,直到成功 while(!actr.apply...
摘要:前言上一篇文章我們講了的同步代碼塊這一篇我們來看看同步代碼塊之間的協作與通信閱讀本篇前你需要知道什么是同步代碼塊什么是監視器鎖還不是很了解的同學建議先去看一看上一篇文章本文的源碼基于系列文章目錄概述在中我們可以使用這個方法來實現同步代碼塊之 前言 上一篇文章我們講了java的同步代碼塊, 這一篇我們來看看同步代碼塊之間的協作與通信. 閱讀本篇前你需要知道什么是同步代碼塊, 什么是監視器...
摘要:不釋放持有的鎖,釋放鎖。在調用方法前,必須持有鎖,調用喚醒,也要持有鎖。休眠一定時間后,進入就緒狀態。這兩個都能被方法中斷當前狀態。用法方獲取鎖判斷條件,不滿足繼續滿足執行其他業務方獲取鎖改變條件通知為什么是而不是會一直循環,直到條件滿足。 sleep和wait sleep是Thread類的方法,wait是Object的方法。 sleep可以到處使用,wait必須是在同步方法或者代碼...
摘要:如果有其它線程調用了相同對象的方法,那么處于該對象的等待池中的線程就會全部進入該對象的鎖池中,從新爭奪鎖的擁有權。 wait,notify 和 notifyAll,這些在多線程中被經常用到的保留關鍵字,在實際開發的時候很多時候卻并沒有被大家重視,而本文則是對這些關鍵字的使用進行描述。 存在即合理 在java中,每個對象都有兩個池,鎖池(monitor)和等待池(waitset),每個...
摘要:用法中規定,在調用者三個方法時,當前線程必須獲得對象鎖。作用方法作用線程自動釋放占有的對象鎖,并等待。當生產者生產了一個數據或者消費者消費了一個數據之后,使用方法來通知所有等待當前對象鎖的線程,但是一次只會有一個等待的線程能拿到鎖。 基礎知識 首先我們需要知道,這幾個都是Object對象的方法。換言之,Java中所有的對象都有這些方法。 public final native void...
閱讀 2432·2021-11-22 13:53
閱讀 1126·2021-09-22 16:06
閱讀 1370·2021-09-02 15:21
閱讀 1895·2019-08-30 15:55
閱讀 3116·2019-08-29 11:19
閱讀 1911·2019-08-26 13:23
閱讀 931·2019-08-23 18:23
閱讀 1747·2019-08-23 16:06