我正在从我的教授的书中学习考试,这段代码使用线程和同步:我们希望每次状态发生变化时都会收到通知(不会错过状态更改)。
public class C {
private int state = 0; // the state
private boolean modified = false; // to show if the state was changed since actualization
public synchronized void printNewState() {
while (true) {
if (!modified) {
wait();
}
System.out.println(state);
modified = false;
notify();
}
}
public synchronized void setValue(int v) {
if (modified) {
wait();
}
state = v;
notify();
modified = true;
System.out.println("value set");
}
}
然后它写了:
但是,无法保证方法SetValue(int)中的notify()唤醒printNewState线程!在Java中我们解决了这个问题
在notifyAll()的帮助下,等待一点忙:
public synchronized void printNewState() {
while (true) {
while (!modified) {
wait();
}
System.out.println(state);
modified = false;
**notify();** \\(?)
}
}
public synchronized void setValue(int v) {
while (modified) {
wait();
}
state = v;
notifyAll();
modified = true;
System.out.println("value set");
}
我不明白为什么通知也没有更改为notifyAll()?可能无法保证此通知转到setValue(int)???的线程
谢谢
答案 0 :(得分:0)
notify()
方法唤醒一个等待线程,而notifyAll()
方法唤醒所有等待线程。问题是,使用notify()
时,被唤醒的线程实际上是随机的。
如果某个其他线程意外或恶意wait()
在同一个对象上,它可能会收到通知,而不是您希望唤醒的线程。
请查看this answer以获取更多信息。对这个答案的评论也很有意思。
修改强>
在您发布的代码示例中,notify()
中的第一个printNewState()
一次只能处理一个更新,因此通知所有等等没有意义发布更新的主题。但是,代码假定只有调用setValue(int)
的线程正在等待。
由于public synchronized void setValue(int)
基本上与将synchronized(this)
作为方法的第一行相同,因此实际上并未保证。任何引用C
类实例的代码都可以等待并搞砸代码。
同步和等待/通知操作应在对象锁定/监视器上发生。 private final Object monitor = new Object()
,synchronized(this.monitor)
,this.monitor.wait()
,this.monitor.notifyAll()
等。
我还要注意modified = true
需要放在notifyAll()
setValue(int)
之前,否则其他等待更新线程将在没有printNewState()
注意到更新的情况下继续进行。< / p>
另外,private boolean modified
应该是private volatile boolean modified
,而private int state
也是如此,尽管AtomicInteger可能是更好的选择。