我是Java并发的新手。我有一个带有3个方法的简单对象,每个方法对应于由3个不同线程运行的代码。为什么在这种情况下notifyAll()语句不释放其他两个线程中的等待?
public class Main {
static class Obj {
synchronized void t1 () {
System.out.println("T1 ran");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
notifyAll();
}
synchronized void t2 () {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T2 ran");
}
synchronized void t3() {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T3 ran");
}
}
public static void main(String[] args) {
final Obj o = new Obj();
new Thread(new Runnable() {
@Override
public void run() {
o.t1();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
o.t2();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
o.t3();
}
}).start();
}}
我期望:T1运行~~暂停1秒~~T2已运行T3运行
我得到了:T1运行
Thread.sleep
不会像wait
那样释放或放松任何锁,因此同步仍然完全有效,其他线程在睡眠期间将不允许进入其方法。
如果更换
Thread.sleep(1000);
带有
wait(1000);
其他线程将被允许捕获相同的锁,输入方法,开始等待,样本将按预期工作。
如果我是正确的,方法t2和t3的线程不能进入该方法,因为线程t1一直在锁定对象,就像它是一个同步的方法一样。当t2和t3实际运行notifyAll()时,已经发生了,所以他们永远等待:(
你应该试着先从t2和t3开始,然后再从t1开始。
正如已经指出的那样。Thread.sleep()不会释放任何锁或监视器,因此其他线程无法输入该方法,因为它被标记为synchronized:Thread.sleen()
您的三个方法是同一实例上的synchronized
。并且CCD_ 4不释放CCD_。所以执行t1
的线程获取锁,休眠一秒钟,唤醒,调用notifyAll()
并完成。
然后,您的另外两个线程分别轮流执行并调用wait()
。但是没有任何东西可以通知他们,所以你的应用程序会被阻止。
你有比赛条件。更改启动线程的顺序,或者像有足够的时间一样运行线程,您可能会看到不同的行为。