Reputation: 27219
From Effective Java (Chapter 10 Concurrency)
Suppose you were to invoke an alien method from within a synchronized region while the invariant protected by the synchronized region was temporarily invalid. Because locks in the Java programming language are reentrant, such calls won’t deadlock
Now look at the following code :
// 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);
}
}
}
So consider SetObservers
and ObservableSet
are two independently written classes and they reside in different package and thus alienMethod()
of SetObserver
is alien to the ObservableSet
class. Now say observers is not in a consistent state when alienMethod
gets called. So where is the question of reentrant locks coming here ? The reentrancy will only come into question if the alien method also synchronizes on the same lock ie `observers' but this doesn't seem to be the case here or am I missing something here ?
Upvotes: 2
Views: 739
Reputation: 200296
And what happens if the alienMethod
causes an event to get fired, which ends up re-entering that same notifyElementAdded
method? This is a real-world hazard, I've been bitten by it once.
In this particular case you must make a safe copy of your list and run through it in peace.
Upvotes: 6