从同步区域调用的重入锁和外来方法(Effective Java item)

时间:2012-07-20 12:39:10

标签: java java.util.concurrent

来自 Effective Java 第10章并发

  

假设   你是在同步区域内调用外来方法的   受同步区域保护的不变量暂时无效。因为   Java编程语言中的锁是可重入的,这样的调用不会死锁

现在看下面的代码:

// Broken - invokes alien method from synchronized block!
public class ObservableSet<E> extends ForwardingSet<E> {
  public ObservableSet(Set<E> set) {
    super(set);
  }

  private final List<SetObserver<E>> observers = new ArrayList<SetObserver<E>>();

  private void notifyElementAdded(E element) {
    synchronized (observers) {
      for (SetObserver<E> observer : observers)
        observer.alienMethod(this, element);
    }
  }
}

因此,考虑SetObserversObservableSet是两个独立编写的类,它们位于不同的包中,因此alienMethod()的{​​{1}}与SetObserver类不同。现在说当调用ObservableSet时观察者不处于一致状态。那么折返锁的问题何在?如果外星人方法也在同一个锁上同步,即“观察者”,那么重入只会产生问题,但这似乎不是这里的情况,或者我在这里遗漏了什么?

1 个答案:

答案 0 :(得分:6)

如果alienMethod导致事件被触发,最终会重新输入相同的notifyElementAdded方法,会发生什么?这是一个现实世界的危险,我曾被它咬过一次。

在这种特殊情况下,您必须制作一份安全的清单副本,并妥善执行。