Scr*_*ers 6 java concurrency multithreading
我正在尝试为自己设计一个类作为Code Kata,它具有可以设置的value属性,并且该类可以发出ValueListener实例.我们的想法是有一个ValueHolder实例,其中许多客户端线程同时访问它.每个客户端线程都请求了ValueWatcher并调用了waitForValue().
我真正在努力的是我应该在wait()周围的while循环中使用什么条件来避免虚假通知(即值没有改变).我可以看到,这种设计可能使ValueWatcher实例错过更新,但在此阶段我不那么担心.
非常感谢任何提供的指导!
public class ValueHolder {
private int value = 0;
private final Object monitor = new Object();
public void setValue(int value) {
synchronized(monitor) {
this.value = value;
monitor.notifyAll();
}
}
ValueWatcher createChangeWatcher() {
return new ValueWatcher();
}
private class ValueWatcher {
public int waitForValue() {
synchronized(monitor) {
while (==== ??? =====) {
monitor.wait();
return value;
}
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
有趣的问题。这是我想到的一个解决方案。具有版本号以及正在更改的值。每当更新该值时,版本号也会增加,因此对象ValueWatcher可以检查版本是否上升,这意味着发生了更改。
编辑:
我最初有一个AtomicLong,但我从@John Vint 那里窃取了包装对象的想法。
private final VersionValue versionValue = new VersionValue();
public void setValue(int value) {
synchronized (monitor) {
versionValue.value = value;
versionValue.version++;
monitor.notifyAll();
}
}
private class ValueWatcher {
private long localVersion = 0;
public int waitForValue() {
synchronized (monitor) {
while (true) {
if (localVersion < versionValue.version) {
// NOTE: the value might have been set twice here
localVersion = versionValue.version;
return versionValue.value;
}
monitor.wait();
}
}
}
}
private static class VersionValue {
int value;
long version;
}
Run Code Online (Sandbox Code Playgroud)
此外,尽管可能出现虚假唤醒,但请务必记住以下内容:
始终在循环内调用 wait 来测试正在等待的条件。不要假设中断是针对您正在等待的特定条件的,或者条件仍然为真。
更多的是关于竞争条件和生产者/消费者模型,而不是虚假唤醒。请参阅我的页面,了解相关内容。