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