并發(fā)編程—等待-通知

有上一篇文章我們知道赋荆,在破壞占用且等待條件的時候,如果兩個資源有一個被占用后懊昨,用的是死循環(huán)的方式來循環(huán)等待窄潭,代碼如下所示:

//循環(huán)的方式 
while (!allocator.apply(this, tar)) ;

如果說apply()操作耗時非常短,而且并發(fā)沖突量不大時酵颁,可以使用這個方案嫉你。如果apply()操作非常耗時,或者并發(fā)沖突量非常大的時候躏惋,這種循環(huán)等待的方案就不適用了幽污,因為這種場景下,可能要循環(huán)上萬次才能獲取到鎖簿姨,相當耗CPU距误。

其實在這種場景下,做好的方案是:如果線程要求的條件不滿足款熬,則線程阻塞自己深寥,進入等待狀態(tài);當線程需要的條件滿足后贤牛,通知等待的線程重新執(zhí)行惋鹅。其中,使用線程阻塞的方式就能避免循環(huán)等待消耗CPU的問題殉簸。

Java中是通過 synchronized 關(guān)鍵字配合 wait()闰集、notify()和notifyAll()這三個方法就能輕松實現(xiàn)沽讹。

如何使用synchronized實現(xiàn)互斥鎖,想必你已經(jīng)很熟悉了武鲁。如下圖所示:

在并發(fā)程序中爽雄,當一個線程進入臨界區(qū)后,由于某些條件不滿足沐鼠,需要進入等待狀態(tài)挚瘟,Java對象wait()方法就能滿足這種需求。當調(diào)用了wait()方法后饲梭,當前線程就會被阻塞乘盖,并且進入右邊的等待隊列中,這個等待隊列也是互斥鎖的等待隊列憔涉。線程在進入等待隊列的同時订框,會釋放持有的互斥鎖,線程釋放鎖后兜叨,其他線程就有機會獲得鎖穿扳,并進入臨界區(qū)了。

當線程需要的條件滿足是国旷,Java中的notify()和notifyAll()方法矛物,就會通知阻塞隊列中的線程高速他條件曾經(jīng)滿足過。因為notify()和notifyAll()只能保證在通知時間點跪但,條件是滿足的泽谨。而被通知線程的執(zhí)行時間點和通知的時間點基本上不會重合,所有當線程執(zhí)行的時候特漩,可能有其他線程已經(jīng)插隊執(zhí)行了,又是條件不滿足了骨杂。

在使用 wait()涂身、notify()和notifyAll()方法時要在synchronized代碼塊中,否則會報java.lang.IllegalMonitorStateException異常搓蚪。

在這個等待-通知機制中蛤售,我們需要考慮一下四個要素:

  1. 互斥鎖:等待-通知首先需要滿足互斥
  2. 線程要求的條件
  3. 何時等待
  4. 何時通知

盡量使用notifyAll

因為notify()方法是隨機地通知等待隊列中的一個線程,而notifyAll()會通知等待隊列中的所有線程妒潭。比如在多生產(chǎn)-多消費者模式中悴能,如果使用notify()方法可能每次喚醒的都是 生產(chǎn)者或者消費者線程,這樣可能會導致某一方始終得不到執(zhí)行機會雳灾。

所以除非經(jīng)過深思熟慮漠酿,否則盡量使用notifyAll()方法。

總結(jié)

等待-通知機制是一種非常普遍的線程間協(xié)作方式谎亩。Java 語言內(nèi)置的 synchronized 配合 wait()炒嘲、notify()宇姚、notifyAll() 這三個方法可以快速實現(xiàn)這種機制,但是它們的使用看上去還是有點復雜夫凸,所以你需要認真理解等待隊列和 wait()浑劳、notify()、notifyAll() 的關(guān)系夭拌。最好用現(xiàn)實世界做個類比魔熏,這樣有助于你的理解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鸽扁,隨后出現(xiàn)的幾起案子蒜绽,更是在濱河造成了極大的恐慌,老刑警劉巖献烦,帶你破解...
    沈念sama閱讀 218,284評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件滓窍,死亡現(xiàn)場離奇詭異,居然都是意外死亡巩那,警方通過查閱死者的電腦和手機吏夯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,115評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來即横,“玉大人噪生,你說我怎么就攤上這事《簦” “怎么了跺嗽?”我有些...
    開封第一講書人閱讀 164,614評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長页藻。 經(jīng)常有香客問我桨嫁,道長,這世上最難降的妖魔是什么份帐? 我笑而不...
    開封第一講書人閱讀 58,671評論 1 293
  • 正文 為了忘掉前任璃吧,我火速辦了婚禮,結(jié)果婚禮上废境,老公的妹妹穿的比我還像新娘畜挨。我一直安慰自己,他們只是感情好噩凹,可當我...
    茶點故事閱讀 67,699評論 6 392
  • 文/花漫 我一把揭開白布巴元。 她就那樣靜靜地躺著,像睡著了一般驮宴。 火紅的嫁衣襯著肌膚如雪逮刨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,562評論 1 305
  • 那天堵泽,我揣著相機與錄音禀忆,去河邊找鬼臊旭。 笑死,一個胖子當著我的面吹牛箩退,可吹牛的內(nèi)容都是我干的离熏。 我是一名探鬼主播,決...
    沈念sama閱讀 40,309評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼戴涝,長吁一口氣:“原來是場噩夢啊……” “哼滋戳!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起啥刻,我...
    開封第一講書人閱讀 39,223評論 0 276
  • 序言:老撾萬榮一對情侶失蹤奸鸯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后可帽,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體娄涩,經(jīng)...
    沈念sama閱讀 45,668評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,859評論 3 336
  • 正文 我和宋清朗相戀三年映跟,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓄拣。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,981評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡努隙,死狀恐怖球恤,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情荸镊,我是刑警寧澤咽斧,帶...
    沈念sama閱讀 35,705評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站躬存,受9級特大地震影響张惹,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜岭洲,卻給世界環(huán)境...
    茶點故事閱讀 41,310評論 3 330
  • 文/蒙蒙 一诵叁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧钦椭,春花似錦、人聲如沸碑诉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,904評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽进栽。三九已至德挣,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間快毛,已是汗流浹背格嗅。 一陣腳步聲響...
    開封第一講書人閱讀 33,023評論 1 270
  • 我被黑心中介騙來泰國打工番挺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屯掖。 一個月前我還...
    沈念sama閱讀 48,146評論 3 370
  • 正文 我出身青樓玄柏,卻偏偏與公主長得像,于是被迫代替她去往敵國和親贴铜。 傳聞我的和親對象是個殘疾皇子粪摘,可洞房花燭夜當晚...
    茶點故事閱讀 44,933評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Java語言為線程的通信提供了支持,其中的一種方式就是等待/通知機制绍坝,java.lang.Object的wait徘意、...
    HRocky閱讀 484評論 0 1
  • 由上一篇文章你應該已經(jīng)知道,在破壞占用且等待條件的時候轩褐,如果轉(zhuǎn)出賬本和轉(zhuǎn)入賬本不滿足同時在文件架上這個條件椎咧,就用死...
    逗逼程序員閱讀 464評論 0 3
  • 在破壞占用且等待條件的時候,如果轉(zhuǎn)出賬本和轉(zhuǎn)入賬本不滿足同時在文件架上這個條件把介,就用死循環(huán)的方式來循環(huán)等待 如果a...
    pixelczx閱讀 388評論 0 1
  • 一個完整的等待 - 通知機制:線程首先獲取互斥鎖勤讽,當線程要求的條件不滿足時,釋放互斥鎖劳澄,進入等待狀態(tài);當要求的條件...
    woshishui1243閱讀 229評論 0 0
  • 久違的晴天地技,家長會。 家長大會開好到教室時秒拔,離放學已經(jīng)沒多少時間了莫矗。班主任說已經(jīng)安排了三個家長分享經(jīng)驗。 放學鈴聲...
    飄雪兒5閱讀 7,523評論 16 22