来自 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);
}
}
}
因此,考虑SetObservers
和ObservableSet
是两个独立编写的类,它们位于不同的包中,因此alienMethod()
的{{1}}与SetObserver
类不同。现在说当调用ObservableSet
时观察者不处于一致状态。那么折返锁的问题何在?如果外星人方法也在同一个锁上同步,即“观察者”,那么重入只会产生问题,但这似乎不是这里的情况,或者我在这里遗漏了什么?
答案 0 :(得分:6)
如果alienMethod
导致事件被触发,最终会重新输入相同的notifyElementAdded
方法,会发生什么?这是一个现实世界的危险,我曾被它咬过一次。
在这种特殊情况下,您必须制作一份安全的清单副本,并妥善执行。