Wednesday, September 11, 2002 02:11 PM
When a normal method is synchronized, the calling thread must obtain a lock on the object (the class instance) before it is allowed to enter the sync block. This does not affect other instances or class (static) data.
If you wish to sync on class data, then the static accessors/mutators for that data must be marked synchronized, and in this case, what happens is exactly what you would expect. Before a thread can enter that block, an object lock associated with the class data must first be acquired. This lock controls access to all static data in the object as though all that static data were just another instance (though it is not, of course), meaning that it doesn't affect any instances or instance data of the object.
This is one reason I've never understood why developers mix static and non-static methods in their classes. When I write a class, I always group the static data and static methods together at the top, and then the instance data, constructors, and instance methods at the bottom.
One thing you should watch out for is deadlocks. A deadlock occurs when thread A has called a sync method on object X, acquired the lock, which in turn calls a sync method on object Y. Meanwhile, thread B has already acquired a lock on object Y by calling a sync method, and that method calls another sync method into object X. What happens? Both threads are put to sleep when they try to acquire each other's locks, and neither will ever be able to release the lock as a result.
How to avoid this? It is advisable that, once within a sync block, you never call into another sync block. It doesn't have to be a direct call either, you can call a method that calls a method that calls a sync method and causes a deadlock. Since it is common for class and instance methods to call back and forth, you have to watch out for this. You don't want thread A calling into a sync instance method and thread B calling into a sync class method and have a deadlock situation result.