多线程并发编程需要注意虚假唤醒Spurious wakeup
虛假喚醒? Spurious wakeup
如果等待線程在沒(méi)有通知被調(diào)用的情況下喚醒,則稱(chēng)為Spurious wakeup。
解決方案就是:
使用while條件判斷,更好的方案是避免使用wait這種低級(jí)的API,而是使用高級(jí)的并發(fā)工具。
?
因?yàn)檫@些高級(jí)的并發(fā)工具都是經(jīng)過(guò)無(wú)數(shù)的坑才提煉出來(lái)的,如果你對(duì)底層缺乏深入的了解比如不知道虛假喚醒那么你沒(méi)有做這種處理,你的代碼可能會(huì)出問(wèn)題。
synchronized(obj){?while(<condition not hold>)obj.wait();?... //執(zhí)行適合條件的操作}
}
這是使用wait()方法的標(biāo)準(zhǔn)習(xí)慣用法。在上面的場(chǎng)景中,如果任何其他線程發(fā)送了notify(),那么條件將不會(huì)成立并且將跳過(guò)wait()。考慮在此線程調(diào)用wait()之前是否沒(méi)有while循環(huán)和其他一些線程調(diào)用通知,然后可能會(huì)發(fā)生它可能永遠(yuǎn)等待或直到調(diào)用下一個(gè)notify。
JDK 5中的等待方法的javadoc也已更新
線程也可以在沒(méi)有被通知,中斷或超時(shí)的情況下喚醒,即所謂的虛假喚醒。雖然這在實(shí)踐中很少發(fā)生,但應(yīng)用程序必須通過(guò)測(cè)試應(yīng)該導(dǎo)致線程被喚醒的條件來(lái)防范它,并且如果條件不滿(mǎn)足則繼續(xù)等待。換句話說(shuō),等待應(yīng)始終在循環(huán)中進(jìn)行
Src:有效的Java作者:Joshua Bloch?https://tech-read.com/2010/01/28/spurious-wakeup-in-java/
https://en.m.wikipedia.org/wiki/Spurious_wakeup
http://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_cond_timedwait.html?
?
==================================
看看其他人對(duì)Doug Lea關(guān)于虛假喚醒的評(píng)論:
https://coderanch.com/t/234023/java/spurious-wakeup
虛假的喚醒是真實(shí)的!?
=============
http://opensourceforgeeks.blogspot.com/2014/08/spurious-wakeups-in-java-and-how-to.html
==============
https://stackoverflow.com/questions/2763714/why-do-pthreads-condition-variable-functions-require-a-mutex
=====================?
對(duì)條件變量(condition variable)的討論
=================================
問(wèn)題代碼分析:
https://www.linuxidc.com/Linux/2014-03/98715.htm
如何修復(fù)問(wèn)題?
#1.? 使用可同步的數(shù)據(jù)結(jié)構(gòu)來(lái)存放數(shù)據(jù),比如LinkedBlockingQueue之類(lèi)。由這些同步的數(shù)據(jù)結(jié)構(gòu)來(lái)完成繁瑣的同步操作。
#2.? 雙層的synchronized使用沒(méi)有意義,保留外層即可。
#3.? 將if替換為while,解決虛假喚醒的問(wèn)題。
總結(jié)
以上是生活随笔為你收集整理的多线程并发编程需要注意虚假唤醒Spurious wakeup的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: qq的个性签名大全
- 下一篇: 一个冷僻的知识点try直接返回final