第十四章 構建自定義的同步工具
阿新 • • 發佈:2018-08-09
循環 信號 滿足 一段 定義 減少 我們 bject 再次
14.1 狀態依賴性管理
基於先檢查後執行的狀態依賴性操作在多線程下常常發生一些我們不希望的結果.因此有必要對狀態依賴操作進行管理,
- 構成前提條件的狀態變量必須有對象的鎖來保護,從而使他們在測試前提條件的同事保持不變.
- 如果條件尚未滿足, 則必須釋放鎖.
- 下次測試前提條件之前則必須重新獲取鎖.之後再進行前提條件的測試
重試的實現方式 :
- 自旋等待. 在條件不成立時一直詢問, 直到條件成立. 會消耗大量的CPU時間
- 休眠. 如果條件不成立, 則休眠一段時間, 休眠過後繼續測試條件是否成立. 響應性較低
- Thread.yield() 在條件不成立時,讓其他線程優先執行
14.2 條件隊列
使得一組線程能夠通過某種方式來等待特定條件變為真.隊列中的元素為線程.
每個Java對象都可以作為一個鎖, 每個鎖都可以擁有一個條件隊列. 內置鎖的條件隊列是非公平的.
Object.wait() 掛起當前線程. 並自動釋放鎖,
Thread.sleep() 掛起當前線程, 不會釋放鎖
14.2.1 條件謂詞
條件謂詞是某個狀態依賴操作的前提條件.
條件等待的三元關系 : 加鎖, 線程掛起, 條件謂詞
條件謂詞包含的狀態變量必須由同一個鎖來保護, 測試條件之前必須先持有這個鎖, 鎖對象和條件隊列對象必須是同一個對象.
使用條件等待:
- 至少有一個條件謂詞
- 在一個循環中調用wait()
- 在wait()返回後再次測試條件謂詞是否成立
14.2.2 通知與喚醒
僅在滿足一下兩種情況事才可以使用 notify()
- 單進單出. 條件變量的每次通知最多只能喚醒一個線程執行.否則會導致信號的丟失,使得某個線程等待一個發生過的信號
- 所有等待線程的類型都相同. 每個線程在wait()返回後執行相同的操作.且只有一個條件謂詞與條件隊列相關.
notify()比notifyall() 更高效,但是也更加危險
通過減少比必要的通知次數可以優化通知的性能.
14.3 顯式的 Condition 對象
同一個條件隊列上等待不同條件謂詞的情況
第十四章 構建自定義的同步工具