日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了

發(fā)布時(shí)間:2024/4/13 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

我來(lái)回答一波。

你可以先將 Thread2 的代碼做以下兩種修改,一種是:

public static class MyThread2 extends Thread {

@Override

public void run() {

while( true ) {

synchronized( OBJ ) {

out.println(Thread.currentThread().getName() + " enter---- " + i);

if( i % 2 == 1 ) {

out.println(Thread.currentThread().getName() + " " + i++);

out.println(Thread.currentThread().getName() + " notify");

OBJ.notify();

} else {

try {

out.println(Thread.currentThread().getName() + " wait");

OBJ.wait();

out.println(Thread.currentThread().getName() + " wait over");

} catch( InterruptedException e ) {

e.printStackTrace();

}

}

out.println(Thread.currentThread().getName() + "leave--- " + i);

}

try {

Thread.sleep(1000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

}

另外一種是:

public static class MyThread2 extends Thread {

@Override

public void run() {

while( true ) {

synchronized( OBJ ) {

out.println(Thread.currentThread().getName() + " enter---- " + i);

if( i % 2 == 1 ) {

out.println(Thread.currentThread().getName() + " " + i++);

out.println(Thread.currentThread().getName() + " notify");

OBJ.notify();

} else {

try {

out.println(Thread.currentThread().getName() + " wait");

OBJ.wait();

out.println(Thread.currentThread().getName() + " wait over");

} catch( InterruptedException e ) {

e.printStackTrace();

}

}

out.println(Thread.currentThread().getName() + "leave--- " + i);

}

Thread.yield();

}

}

}

這兩種改法你分別運(yùn)行一下,會(huì)發(fā)現(xiàn)第一種改法運(yùn)行以后能得到你想要的結(jié)果。

而第二種改法,答案是不一定,并且最終極大可能還是會(huì)把兩個(gè)線(xiàn)程堵死。

你的代碼的運(yùn)行結(jié)果跟你的預(yù)期不符,主要你忽視了兩點(diǎn):

CPU時(shí)間片

wait被notify后,不會(huì)立即獲得鎖。

Java 的對(duì)象鎖的實(shí)現(xiàn)采用的是Monitor機(jī)制,具體機(jī)制如下,你也可以參考我寫(xiě)過(guò)的一篇文章:

當(dāng)一個(gè)線(xiàn)程需要獲取 Object 的鎖時(shí),會(huì)被放入 EntrySet 中進(jìn)行等待,如果該線(xiàn)程獲取到了鎖,成為當(dāng)前鎖的 owner。如果根據(jù)程序邏輯,一個(gè)已經(jīng)獲得了鎖的線(xiàn)程缺少某些外部條件,而無(wú)法繼續(xù)進(jìn)行下去(例如生產(chǎn)者發(fā)現(xiàn)隊(duì)列已滿(mǎn)或者消費(fèi)者發(fā)現(xiàn)隊(duì)列為空),那么該線(xiàn)程可以通過(guò)調(diào)用 wait 方法將鎖釋放,進(jìn)入 wait set 中阻塞進(jìn)行等待,其它線(xiàn)程在這個(gè)時(shí)候有機(jī)會(huì)獲得鎖,去干其它的事情,從而使得之前不成立的外部條件成立,這樣先前被阻塞的線(xiàn)程就可以重新進(jìn)入 EntrySet 去競(jìng)爭(zhēng)鎖。

你的Thread2調(diào)完notify后,Thread1等到Thread2釋放鎖以后,它還得和 Thread2 站在同一條起跑線(xiàn)上去競(jìng)爭(zhēng)鎖,所以沒(méi)有絕對(duì)地說(shuō)Thread2釋放鎖以后,Thread1一定就輪到它獲得鎖。

你的代碼每次都運(yùn)行相同的結(jié)果,原因主要在于 Thread2 會(huì)比 Thread1 更容易重新獲得鎖,因?yàn)門(mén)hread2的CPU時(shí)間片極大可能還沒(méi)用完。

我們上面的修改,第一種修改是讓 Thread2 sleep 一秒,這絕對(duì)能讓Thread1 有充足的時(shí)間獲取鎖,所以運(yùn)行結(jié)果會(huì)如你所預(yù)期。

第二種修改是讓 Thread2 讓出 CPU 時(shí)間片,但是同樣,CPU 在重新選擇線(xiàn)程運(yùn)行的時(shí)候,至少會(huì)有一半的機(jī)會(huì)還是會(huì)選中 Thread2。

以上。希望能幫到你。

總結(jié)

以上是生活随笔為你收集整理的java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。