On 12/2/2010 3:48 PM, Patricia Shanahan wrote:
Gregg Wonderly wrote:
...
A second issue is that if you are designing a "container" class that others
might use in multiplicity such that it could end up in a container, and
perhaps as a key data structure, it can be better to create an internal
locking object to perform synchronization on so that if the user of your class
starts using your class as a locking object, the internal locking does not
impact unrelated code paths.
...
For container objects, I would give the opposite advice, and recommend making
the container itself the lock object.
There are cases for both I believe. ConcurrentHashMap, for example has no locks
performed on the instance. All locking is internal using mechanisms other than
synchronized.
The primary issue with using an internal lock, for me, is that I've found that I
end up with less opportunity for circular wait if I am in complete control of
when a lock is asserted.
For things where atomic views need to maintained through multiple operations on
the same instance, then a single global view lock will be important. As the
user of the container instance, you are more able to understand that need in
your application, so locking is your responsibility.
Many people have complained about CHM not being "the lock" itself, but it really
comes down to the fact that since it does not use synchronized actions
internally, it can not make the object be "the lock".
With this in mind, I've started trying to internalize more locking so that for
things that I do need to "adjust internal performance" on, I don't have to go
everywhere else and change locking use to be in line with the change from
synchronized to Lock.
Locking with instances via synchronized was convenient, but I'd suggest that not
doing that provides a more plastic model that you can more readily adjust.
I also find that I will put more application operations into the APIs to help me
control and optimize those usage patterns. This seems to help me create more
relevant/useful APIs and fewer "containers". I.e. more simple algorithms end up
in the class implementation instead of strewn about the application.
Gregg Wonderly