Friday, June 25, 2010

Thread safety and Synchronization at Class level in Java

Thread safety and Synchronization at Class level in Java

Can someone throw some light on the behaviour of class/object level monitor in java? Does one takes 
precedence over other? What happens when, class has both synchronized instance methods and synchronized static methods? 
Does calling thread has to acquire both class/object locks?

Answer:
    Those locks are not related, and each needs to be obtained regardless of the other. Namely, if you have:
    
    class Foo{
        static synchronized void staticMethod(){}
        synchronized void instanceMethod(){}
    }

    And then an instance: Foo f=new Foo();
    
    Then you have 2 unrelated monitors (one for class Foo, one for instance f ). Any threads attempting to invoke 
    staticMethod() will need to gain access to the (single) class monitor, and nothing else. Any threads calling 
    f.instanceMethod() will need to gain access to "f" monitor, and nothing else.
    
    If you need any access hierarchy, you'll need to do it programatically, which may look as follows (however, beware 
    - such nested locks pose some dangers of deadlocks unless used with care):
    
    synchronized(Foo.class){
        synchronized(f){
            // my code
        }
    } 

    -------------------------------------------------------------
    A synchronized method acquires a lock before it executes. For a class (static) method, the lock associated with the 
    Class object for the method's class is used. For an instance method, the lock associated with this (the object for 
    which the method was invoked) is used.

    class Test {
        int count;
        synchronized void bump() { 
            count++; 
        }
        static int classCount;
        static synchronized void classBump() {
            classCount++;
        }
    }

    It has exactly the same effect as:
    -------------------------
    class BumpTest {
        int count;
        void bump() {
            synchronized (this) {
                count++;
            }
        }
        static int classCount;
        static void classBump() {
            try {
                synchronized (Class.forName("BumpTest")) {
                    classCount++;
                }
            } catch (ClassNotFoundException e) {
            ...
            }
        }
    }
    -------------------------

    I assume that since we are dealing with 2 different locks then Class lock will lock all static synch methods and 
    'this' lock will lock all synch instance methods.
----------------------------------------------------------
Actually we should follow a standard policy here called "Don't Wake The Zombies", basically, rather than wake up a 
5 year old thread. However, if You ask only one synchronized static method can be called at a time. The answer is yes, 
for a given Class, only one synchronized static method can be called at a time. Synchronized static methods of different 
Classes, however, can be called at the same time, because the lock is on different instances of the Class object.

-------------------------------------------END------------------------------------------

No comments:

Post a Comment