【发布时间】:2016-02-19 15:16:24
【问题描述】:
考虑以下代码示例:
private Object lock = new Object();
private volatile boolean doWait = true;
public void conditionalWait() throws Exception {
synchronized (lock) {
if (doWait) {
lock.wait();
}
}
}
public void cancelWait() throws Exception {
doWait = false;
synchronized (lock) {
lock.notifyAll();
}
}
如果我正确理解了Java Memory Model,那么上面的代码不是线程安全的。它很可能会阻塞,因为编译器可能会决定重新排列代码如下:
public void cancelWait() throws Exception {
synchronized (lock) {
lock.notifyAll();
}
doWait = false;
}
在这种情况下,线程 T1 可能会调用cancelWait() 方法,获取锁,调用notifyAll() 并释放锁。在此之后,并行线程 T2 可以调用 conditionalWait() 并获取现在可用的锁。变量doWait 的值仍然为true,因此线程T2 执行lock.wait() 并阻塞。
我的理解正确吗?如果不是,请提供 Java 规范中反驳上述情况的相应参考资料。
是否有解决此问题的解决方案不需要需要将doWait 拉入同步块?
【问题讨论】:
-
如果我错了,请纠正我,但就目前而言,是否任何调用 conditionalWait 的线程(当 doWait 为真时)都必须无限期等待? cancelWait 尝试获取从 conditionalWait 锁定的同一对象上的锁定,因此永远无法执行 notifyAll。
-
@user1431765
wait()释放锁,所以其他线程可以获取锁。
标签: java multithreading synchronization synchronized volatile