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

Reply via email to