java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了
我來(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)題。
- 上一篇: Java中头指针和头结点_. 2 . 【
- 下一篇: 零基础自学java的难处_零基础自学Ja