java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了
我來回答一波。
你可以先將 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();
}
}
}
這兩種改法你分別運行一下,會發現第一種改法運行以后能得到你想要的結果。
而第二種改法,答案是不一定,并且最終極大可能還是會把兩個線程堵死。
你的代碼的運行結果跟你的預期不符,主要你忽視了兩點:
CPU時間片
wait被notify后,不會立即獲得鎖。
Java 的對象鎖的實現采用的是Monitor機制,具體機制如下,你也可以參考我寫過的一篇文章:
當一個線程需要獲取 Object 的鎖時,會被放入 EntrySet 中進行等待,如果該線程獲取到了鎖,成為當前鎖的 owner。如果根據程序邏輯,一個已經獲得了鎖的線程缺少某些外部條件,而無法繼續進行下去(例如生產者發現隊列已滿或者消費者發現隊列為空),那么該線程可以通過調用 wait 方法將鎖釋放,進入 wait set 中阻塞進行等待,其它線程在這個時候有機會獲得鎖,去干其它的事情,從而使得之前不成立的外部條件成立,這樣先前被阻塞的線程就可以重新進入 EntrySet 去競爭鎖。
你的Thread2調完notify后,Thread1等到Thread2釋放鎖以后,它還得和 Thread2 站在同一條起跑線上去競爭鎖,所以沒有絕對地說Thread2釋放鎖以后,Thread1一定就輪到它獲得鎖。
你的代碼每次都運行相同的結果,原因主要在于 Thread2 會比 Thread1 更容易重新獲得鎖,因為Thread2的CPU時間片極大可能還沒用完。
我們上面的修改,第一種修改是讓 Thread2 sleep 一秒,這絕對能讓Thread1 有充足的時間獲取鎖,所以運行結果會如你所預期。
第二種修改是讓 Thread2 讓出 CPU 時間片,但是同樣,CPU 在重新選擇線程運行的時候,至少會有一半的機會還是會選中 Thread2。
以上。希望能幫到你。
總結
以上是生活随笔為你收集整理的java 阻塞 wait_java交替打印奇偶数问题,会出现2个线程都wait阻塞了的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Java中头指针和头结点_. 2 . 【
- 下一篇: 零基础自学java的难处_零基础自学Ja