计数器更改时通知主题 [英] Notify Threads When Counter Changes

查看:106
本文介绍了计数器更改时通知主题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想设计一个类作为Code Kata为自己,有一个value属性可以设置,该类可以发出ValueListener实例。这个想法是有一个ValueHolder的实例,许多客户端线程同时访问它。每个客户端线程都请求了一个ValueWatcher并调用了waitForValue()。

I am trying to design a class as a Code Kata for myself that has a value property that can be set, and the class can issue ValueListener instances. The idea is that there is one instance of ValueHolder with many client threads accessing it concurrently. Each client thread has requested a ValueWatcher and has called waitForValue().

我真正努力的是什么条件我应该使用while循环的wait以避免虚假通知(即值没有改变)。我可以看到,这个设计可能会使ValueWatcher实例错过更新,但在这个阶段不太担心。

What I am really struggling with is what condition I should use on the while loop around the wait() to avoid spurious notifications (i.e. value hasn't changed). I can see that this design may make it possible of ValueWatcher instances to miss updates, but am less worried about that at this stage.

感谢任何指导! / p>

Would appreciate any guidance on offer!

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;
        }
      }
    }
  }     
}


推荐答案

有趣的问题。这里有一个解决方案,我的头顶。有一个版本号以及要更改的值。每当更新值时,版本号也会增加,因此 ValueWatcher 对象可以检查版本是否上升,这意味着发生了更改。

Interesting problem. Here's one solution off the top of my head. Have a version number along with the value that is being changed. Whenever the value is updated, the version number is also incremented so the ValueWatcher objects can then check to see if the version went up meaning a change has happened.

编辑:
我最初有一个 AtomicLong ,但我偷了一个包装的想法对象从@John Vint。

I initially had an AtomicLong but I am stealing the idea of a wrapper object from @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;
}






此外,虽然虚假的唤醒有可能重要的是要记住文本:


Also, although spurious wakeups are possible it is important to remember that the text:


始终在循环中调用wait,以测试正在等待的条件。不要假定中断是针对您正在等待的特定条件,或者条件仍然是真的。

Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.

关于种族条件和生产者/消费者模型,而不是假的唤醒。请参阅我的网页

Is more about race conditions and producer/consumer models than spurious wakeups. See my page here about that.

这篇关于计数器更改时通知主题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆