多线程并发编程需要注意虚假唤醒Spurious wakeup
虛假喚醒? Spurious wakeup
如果等待線程在沒有通知被調用的情況下喚醒,則稱為Spurious wakeup。
解決方案就是:
使用while條件判斷,更好的方案是避免使用wait這種低級的API,而是使用高級的并發工具。
?
因為這些高級的并發工具都是經過無數的坑才提煉出來的,如果你對底層缺乏深入的了解比如不知道虛假喚醒那么你沒有做這種處理,你的代碼可能會出問題。
synchronized(obj){?while(<condition not hold>)obj.wait();?... //執行適合條件的操作}
}
這是使用wait()方法的標準習慣用法。在上面的場景中,如果任何其他線程發送了notify(),那么條件將不會成立并且將跳過wait()。考慮在此線程調用wait()之前是否沒有while循環和其他一些線程調用通知,然后可能會發生它可能永遠等待或直到調用下一個notify。
JDK 5中的等待方法的javadoc也已更新
線程也可以在沒有被通知,中斷或超時的情況下喚醒,即所謂的虛假喚醒。雖然這在實踐中很少發生,但應用程序必須通過測試應該導致線程被喚醒的條件來防范它,并且如果條件不滿足則繼續等待。換句話說,等待應始終在循環中進行
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?
?
==================================
看看其他人對Doug Lea關于虛假喚醒的評論:
https://coderanch.com/t/234023/java/spurious-wakeup
虛假的喚醒是真實的!?
=============
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
=====================?
對條件變量(condition variable)的討論
=================================
問題代碼分析:
https://www.linuxidc.com/Linux/2014-03/98715.htm
如何修復問題?
#1.? 使用可同步的數據結構來存放數據,比如LinkedBlockingQueue之類。由這些同步的數據結構來完成繁瑣的同步操作。
#2.? 雙層的synchronized使用沒有意義,保留外層即可。
#3.? 將if替換為while,解決虛假喚醒的問題。
總結
以上是生活随笔為你收集整理的多线程并发编程需要注意虚假唤醒Spurious wakeup的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: qq的个性签名大全
- 下一篇: 一个冷僻的知识点try直接返回final