我很想在這里提交一個我制作的簡短示例,并希望有人能夠向我解釋一件事:是否可以在同步塊內使用 wait() 和 notify() 而不必顯式宣告執行緒?(又名:不使用專用執行緒)。
這是示例:
public class mutex {
private Object mutex = new Object();
public mutex(Object mutex) {
this.mutex = mutex;
}
public void step1() throws InterruptedException {
System.out.println("acquiring lock");
synchronized(mutex) {
System.out.println("got in sync block");
System.out.println("calling wait");
mutex.wait();
System.out.println("wait finished ");
}
}
public void step2() throws InterruptedException{
System.out.println("acquiring lock");
synchronized(mutex){
System.out.println("got in sync block");
System.out.println("calling notify");
mutex.notify();
System.out.println("notify called");
}
}
這兩個簡單的步驟只是列印日志和應該發生的事情。這個想法是能夠在 step1 中呼叫 wait(),并在 step2 被其 notify() 呼叫后能夠完成呼叫。
現在,據我了解整個事情,這是做我想做的事情的正確方法:
public void go1() {
Object mutex = new Object();
mutex m = new mutex(mutex);
Thread t1 = new Thread(()->{
try {
m.step1();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
Thread t2 = new Thread(()->{
try {
Thread.sleep(1000);
m.step2();
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
t2.start();
}
最后是主要的
public static void main(String[] args) {
Object mutex = new Object();
new mutex(mutex).go1();
//new mutex(mutex).go2();
}
上面的代碼有效并顯示了我的期望:
acquiring lock
got in sync block
calling wait
acquiring lock
got in sync block
calling notify
notify called
wait finished
我明白它為什么有效。這是我期望發生的事情,也是我被教導如何做到這一點的。現在問題來了,因為我將粘貼我想測驗的主函式的第二個變體——這個只是在呼叫 wait() 時掛起。
public void go2() {
Object mutex = new Object();
mutex m = new mutex(mutex);
try {
m.step1();
Thread.sleep(1000);
m.step2();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
為什么會掛起?是不是因為只有一個執行緒在做所有事情,并且在呼叫 wait() 后進入等待狀態?我知道當在監視器物件上呼叫 wait 時,它也應該釋放鎖,那么為什么在這種情況下程式不能呼叫 step2() 呢?有沒有辦法使用我的第二個 go() 函式來實作這個程序,或者它不可能作業?
TLDR 只是為了確保我可以理解:我是否必須使用專用執行緒才能正確使用 wait() 和 notify()?因為如果我不這樣做,我似乎會陷入僵局。
謝謝你。
uj5u.com熱心網友回復:
一旦呼叫mutex#wait,當前執行緒就被添加到物件的等待集中mutex。并且執行緒將不會執行任何進一步的指令,直到它從mutex' 的等待集中洗掉。這就是為什么step2不能被當前執行緒執行的原因。
當前執行緒將從等待集中移除并在其他執行緒呼叫時恢復mutex#notify/notifyAll。有關當前執行緒可以恢復的所有情況,請參見JLS#WAIT 。
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/517041.html
標籤:爪哇多线程并发等待通知
