Reputation: 545
Looking at the implementation of Collection's SynchronizedList i recognized that all access on the internal list is synchronized by locking on the wrapper's final member "mutex". As all access is synchronized on the same object, why dont we ommit the extra mutex object and just synchronize on the list itself? Is it only because of the fact that anybody else could synchronize on that list and we might get deadlocks? I am asking, because i consider to implement a container-class, that holds two lists. The container offers e.g. .addToL1(...) and .addToL2(...). In this case the inner lists are not accessible, so it should be sufficient to synchronize on the lists intrinsically, correct?
Upvotes: 1
Views: 337
Reputation: 49794
In this case it is specifically done because sublists created from the list have to synchronize on the parent object
public List<E> subList(int fromIndex, int toIndex) {
synchronized(mutex) {
return new SynchronizedList<E>(list.subList(fromIndex, toIndex),
mutex);
}
}
If you create your synchronized list by Collections.synchronizedList( list );
, it will set the mutex to this
(that is, the synchronized list object itself).
But you can also call Collections.synchronizedList()
with two parameters, the second of which will then be used as the mutex.
And as in general it isn't a good idea to synchronize on publicly visible objects, I prefer to always use the 2 parameter version and hide the mutex object from clients of the code.
Upvotes: 2
Reputation: 533660
The most robust solution is to lock on an object that the caller has no way of getting access to. (We will ignore reflection and Unsafe for a moment) The JDK developers have to consider the worst thing any developer could do with the library because someone will do that and things they couldn't have thought of.
However, sometimes simplicity is the most important driver esp if you know who will be using it and understand its limitations.
Upvotes: 2