Saturday, 6 August 2011

How does JVM handle synchronization?

We have seen how the JVM organizes the program into runtime data areas in my previous blog. We know that each thread has its own stack and that all the threads in the program share the heap. The heap contains all the objects created within the program including the thread. The method area contains all the class /static variables of a classes used by the program. These variables are available to all the threads in the program.

Now we know that we have two data areas which contains data shared by all threads.
1. the heap and 2. the method area

So if two threads try to access the objects or class variables in these areas concurrently, then the data need to be properly managed else we will end up with inconsistent data. This situation can be handled through synchronization and java manages this through the use of 'monitor'. Hence monitor acts as a guardian over a piece of code, so that no two threads execute that code simultaneously.
Java's monitor supports two kinds of synchronization: mutual exclusion and cooperation

  • Mutual exclusion is achieved in JVM through the use of object or class blocks , they enable multiple threads to work independently on shared data without interfering with  each other. 
  • While Cooperation in JVM is achieved through the use of object wait, notify and notifyAll methods.

Each monitor is associated with an object reference. Whenever a thread reaches the code which is synchronized, it must obtain a lock on the referenced object failing which it will have to wait (block on synchronization state). Once the thread obtains the lock the JVM increases the count of the number of times an object has been locked. The same thread can lock the same object multiple times. Whenever the thread releases/relinquishes the lock the count is decremented. When there are no more locks on the object i.e count returns to zero, then any other thread can obtain the lock on the object if needed.

Synchronization is supported by the java language  in two ways

  1. synchronized method : Whenever the JVM encounters a symbolic reference to the method and realizes its a synchronized method, then it tries to obtains the lock from the monitor. If the lock is obtained then the synchronized method is executed and once all the statements are processed or the code throws an exception the lock is released. For an instance method, a lock is obtained on the object, of which synchronized method is invoked. In case of static synchronized method the lock is obtained on the class object. The JVM does not use special op-codes to invoke or return from method level synchronization.
  2. synchronized statement (Block of code): The JVM uses two special op codes monitorenter and monitorexit whenever a thread enters or exits the synchronized block of code. When the JVM's encounters monitorenter  it tries to obtain a lock on the object referred to by objectref on the stack. If the lock is already obtained the the count is incremented by one and whenever the monitorexit  is encountered the count is decremented by one. When the count reaches zero the lock is released.


No comments:

Post a Comment