激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專注于服務(wù)器技術(shù)及軟件下載分享
分類導(dǎo)航

PHP教程|ASP.NET教程|JAVA教程|ASP教程|

服務(wù)器之家 - 編程語言 - JAVA教程 - 詳解Java程序并發(fā)的Wait-Notify機制

詳解Java程序并發(fā)的Wait-Notify機制

2019-12-30 14:11低調(diào)小一 JAVA教程

這篇文章主要介紹了詳解Java程序并發(fā)的Wait-Notify機制,多線程并發(fā)是Java編程中的重要部分,需要的朋友可以參考下

Wait-Notify場景
典型的Wait-Notify場景一般與以下兩個內(nèi)容相關(guān):
1. 狀態(tài)變量(State Variable)
當(dāng)線程需要wait的時候,總是因為一些條件得不到滿足導(dǎo)致的。例如往隊列里填充數(shù)據(jù),當(dāng)隊列元素已經(jīng)滿時,線程就需要wait停止運行。當(dāng)隊列元素有空缺時,再繼續(xù)自己的執(zhí)行。
2. 條件斷言(Condition Predicate)
當(dāng)線程確定是否進入wait或者是從notify醒來的時候是否繼續(xù)往下執(zhí)行,大部分都要測試狀態(tài)條件是否滿足。例如,往隊列里添加元素,隊列已滿,于是阻塞當(dāng)前線程,當(dāng)有其他線程從隊列里取走了元素,就通知在等待的線程“隊列有剩余空間,可以往里添加元素了”。這時,等待添加元素的進程就會被喚醒,然后判斷一下當(dāng)前隊列是否真的有剩余空間,如果真的有剩余空間,就將元素添加進去,如果沒有,則繼續(xù)阻塞等待下次喚醒。
3. 條件隊列(Condition Queue)
每個對象都有一個內(nèi)置的條件隊列,當(dāng)一個線程在該對象鎖上調(diào)用wait函數(shù)的時候,就會將該線程加入到該對象的條件隊列中。

注意
wait與notify是Java同步機制中的重要組成部分。結(jié)合與synchronized關(guān)鍵字使用,可以建立很多優(yōu)秀的同步模型,例如生產(chǎn)者-消費者模型。但是在使用wait()、notify()、notifyAll()函數(shù)的時候,需要特別注意以下幾點:

    wait()、notify()、notifyAll()方法不屬于Thread類,而是屬于Object基礎(chǔ)類,也就是說每個對象都有wait()、notify()、notifyAll()的功能。因為每個對象都有鎖,鎖是每個對象的基礎(chǔ),因此操作鎖的方法也是最基礎(chǔ)的。
    調(diào)用obj的wait(), notify()方法前,必須獲得obj鎖,也就是必須寫在synchronized(obj){...} 代碼段內(nèi)。
    調(diào)用obj.wait()后,線程A就釋放了obj的鎖,否則線程B無法獲得obj鎖,也就無法在synchronized(obj){...} 代碼段內(nèi)喚醒線程A。
    當(dāng)obj.wait()方法返回后,線程A需要再次獲得obj鎖,才能繼續(xù)執(zhí)行。
    如果線程A1,A2,A3都在obj.wait(),則線程B調(diào)用obj.notify()只能喚醒線程A1,A2,A3中的一個(具體哪一個由JVM決定)。
    如果線程B調(diào)用obj.notifyAll()則能全部喚醒等待的線程A1,A2,A3,但是等待的線程要繼續(xù)執(zhí)行obj.wait()的下一條語句,必須獲得obj鎖。因此,線程A1,A2,A3只有一個有機會獲得鎖繼續(xù)執(zhí)行,例如A1,其余的需要等待A1釋放obj鎖之后才能繼續(xù)執(zhí)行。
    當(dāng)線程B調(diào)用obj.notify()或者obj.notifyAll()的時候,線程B正持有obj鎖,因此,線程A1,A2,A3雖被喚醒,但是仍無法獲得obj鎖。直到線程B退出synchronized代碼塊,釋放obj鎖后,線程A1,A2,A3中的一個才有機會獲得對象鎖并得以繼續(xù)執(zhí)行。


示例代碼
線程的wait操作的典型代碼結(jié)構(gòu)如下:

?
1
2
3
4
5
6
7
public void test() throws InterruptedException {
  synchronized(obj) {
    while (! contidition) {
      obj.wait();
    }
  }
}

為什么obj.wait()操作必須位于循環(huán)中呢?有以下幾個主要原因:
1. 一個對象鎖可能用于保護多個狀態(tài)變量,當(dāng)它們都需要wait-notify操作時,如果不將wait放到while循環(huán)中就會有問題。例如,某對象鎖obj保護兩種狀態(tài)變量a和b,當(dāng)a的條件斷言不成立時發(fā)生了wait操作,當(dāng)b的條件斷言不成立時也發(fā)生了wait操作,兩個線程被加入到obj對應(yīng)的條件隊列中。現(xiàn)在若改變狀態(tài)變量a的某操作發(fā)生,在obj上調(diào)用了notifyAll操作,則obj對應(yīng)的條件隊列里的所有線程均被喚醒,之前等待a的一個或幾個線程去判斷a的條件斷言可能成立了,但是b對于的條件斷言肯定仍不成立,而此時等待b的線程也被喚醒了,所以需要循環(huán)判斷b的條件斷言是否滿足,如果不滿足,則繼續(xù)wait。
2. 多個線程wait的同一狀態(tài)的條件斷言。例如,向隊列添加元素的場景,當(dāng)前隊列是滿的,多個線程想往里面添加元素,于是都wait了。此時,另一個線程從隊列里取出了一個元素,調(diào)用了notifyAll操作,喚醒了所有線程,但是只有一個線程能夠往隊列里添加一個元素,其他的仍需要等待。
3. 虛假喚醒。在沒有被通知、中斷或超時的情況下,線程自動蘇醒了。雖然這種情況在實踐中很少發(fā)生,但是通過循環(huán)等待可以杜絕這一情況的發(fā)生。

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: av在线免费网 | 成人三级电影在线 | 亚洲一级簧片 | 欧产日产国产精品99 | 日韩大片在线永久观看视频网站免费 | 欧美女同hd| 美国黄色毛片女人性生活片 | 国产乱一区二区三区视频 | 色柚视频网站ww色 | 成人在线视频黄色 | 久久久久久久一区二区三区 | 精品在线免费播放 | 日本高清无遮挡 | 末成年女av片一区二区 | 91精品国产网站 | 亚洲一区在线国产 | 欧美a在线观看 | 欧美日韩一区,二区,三区,久久精品 | 欧美日韩网站在线观看 | 中文字幕精品一二三四五六七八 | 国产91精品久久久 | 欧美精品一区二区三区久久久 | 69av导航 | 国产午夜精品理论片a级探花 | 一级黄色影片在线观看 | 天天操天天碰 | 中文字幕欧美在线 | 欧美成人免费电影 | 国产a级网站 | 国产精品久久久久久久午夜片 | 国产成人高潮免费观看精品 | 老司机免费福利午夜入口ae58 | 国产毛片aaa一区二区三区视频 | 精品视频一区二区三区四区 | 国产亚洲欧美在线视频 | 免费a级毛片永久免费 | 成人男女啪啪免费观看网站四虎 | 久久国产中文字幕 | 国内精品久久久久久久星辰影视 | 欧美精品一区二区久久久 | 成人辣文 |