Which monitor is used when a static method is synchronized

adminguy's picture
Posted March 18th, 2015 by adminguy

                          

 

 

When a synchronized method of an object is invoked, semantics for thread safety require the calling thread to first grab the monitor of that object. At times the calling thread gets the monitor as soon as it requests it, but at times -- if another thread has already grabbed the monitor -- the calling thread may have to wait till it's released. Every object in Java has one (and only one) monitor, which is logical because the semantics of thread safety needs to ensure that only one thread can enter code protected by the synchronized keyword. 

 
So when a thread requests to enter a synchronized instance method of an object, the object will release it's monitor to that thread before it enters the method and take the monitor back after the it exits the synchronized method. But, what do you think should happen when a thread tries to enter a static synchronized method? Because static methods don't belong to individual objects, the calling thread cannot request for the object's monitor. Which monitor should it get?
 
To understand this we have to take a dip back to the basics. Static members don't belong to individual objects, but they aren't orphans either, they do belong to the class. And every class loaded by the JVM is simultaneously represented by an object of type Class. When a thread attempts to enter a synchronized static method, it will ask for the monitor of the Class object that represents the class within which the static method exists. 
 
Let's understand this with an example.

 
public class SafeCounter {
 
    private static int globalCounter;
   
    private int instanceCounter ;
 
    public synchronized static int getNextGlobalCount() {
        return globalCounter ++;
    }
   
    public synchronized int getNextInstanceCount() {
        return instanceCounter ++;
    }
 
}
 
Code Example 1
 
The class shown in Code Example 1 is a thread safe counter which maintains two counter variables: the first is a global counter which could be used to maintain the count of some entity across the entire software application; and the second is an instance counter which could be used by individual instances of client classes to maintain the count of something that's local to them. 
 
The static variable globalCounter represents the global counter and is incremented in the static method getNextGlobalCount(). The instance variable instanceCounter represents the local counter and is incremented in the instance method getNextInstanceCounter().
 
When a thread invokes the instance method getNextInstanceCount(), it will grab the objects monitor, and when it invokes the static method getNextGlobalCount() it will grab the monitor of the Class object which represents the SafeCounter class.