【问题标题】:Should I synchronize notifyObservers calls?我应该同步 notifyObservers 调用吗?
【发布时间】:2017-01-14 07:42:48
【问题描述】:

我找到了 Observable 的这个实现:

public class ObservableObject extends Observable {
    private static ObservableObject instance = new ObservableObject();

    public static ObservableObject getInstance() {
        return instance;
    }

    private ObservableObject() {
    }

    public void updateValue(Object data) {
        synchronized (this) {
            // The call to setChanged marks this Observable object as having been changed; the hasChanged method will now return true.
            setChanged();
            notifyObservers(data);
        }
    }
}

我想了解的是default implementation 使用同步块和在我上面找到的代码中使用同步块有什么区别,两者都需要吗?,有没有更好的(正确)方式?

【问题讨论】:

  • 我相信除了锁定同一个对象两次之外没有什么区别,因为默认实现使用 Observable 实例来获取锁,而你的类 ObservableObjectObservable 的子类,在这两个实例中当前的ObservableObject 实例将被锁定
  • @ManZzup 默认实现锁定数据,而给定实现锁定自身

标签: java multithreading observable observer-pattern synchronized


【解决方案1】:

您不应该在持有锁的情况下调用 notifyObservers。由于链接代码的 cmets 中引用的原因,发布的代码存在缺陷:

我们不希望 Observer 在拥有自己的 Monitor 的同时对任意代码进行回调。我们从 Vector 中提取每个 Observable 并存储 Observer 状态的代码需要同步,但通知观察者不需要(不应该)。这里任何潜在竞争条件的最坏结果是:

1) 新添加的观察者将错过正在进行的通知

2) 最近未注册的 Observer 不关心时会被错误通知

notifyObservers 方法包括更新观察者的调用,java.util.Observable 代码小心翼翼地让观察者保持不同步。如果 observable 在更新观察者时持有自己的锁,而 observable 无法控制观察者的行为,则不知道锁可以持有多长时间,从而影响 observable 的响应能力。

【讨论】:

  • 谢谢,你的解释有帮助。
猜你喜欢
  • 1970-01-01
  • 2020-03-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-17
  • 1970-01-01
  • 2013-04-13
  • 2012-01-05
相关资源
最近更新 更多