Sunday, July 13, 2014

Understanding Synchronization

In a multi-threaded program, when 2 or more threads try to access a common resource there needs to be a way to ensure that only one thread uses the resource at a time. The process by which this is achieved is called synchronization. Java provides language constructs to achieve using synchronized keyword.

To understand synchronization better it is necessary to learn the concept of monitor. Monitor is an object that acts as a mutually exclusive lock. Only one thread can own a monitor at a time. A thread acquires a lock on the monitor to access a shared resource. All other threads attempting to access the shared resource will wait until first thread exits the monitor.

Synchronized Methods

Synchronized methods is one the two synchronization idioms available in Java. In synchronized methods synchronized keyword is added at the method level. It is not possible for two invocations of the synchronized methods on the same object to interleave. When one thread is executing a synchronized method all other threads that invoke the synchronized methods block. Synchronized methods also ensures that state of the changes in the object is visible to all threads (happens before relationship) when the methods exits.

public class ThreadSync {

 class MyCounter {
  int count = 0;
  MyCounter() {   
  }
  public synchronized void increment() {
   count = count + 1;
  }
 }
 
 class MyThread extends Thread {
  MyCounter counter = null;
  MyThread(MyCounter counter) {
   this.counter = counter;
  }
  public void run() {
   counter.increment();
  }
 }
 
 public static void main(String[] args) {
  ThreadSync ts = new ThreadSync();
  MyCounter counter = ts.new MyCounter();
  Thread t1 = ts.new MyThread(counter);
  Thread t2 = ts.new MyThread(counter);
  t1.start();
  t2.start();
 }
}

Synchronized Statements

Synchronized statements is another approach of achieving synchronization in Java. This approach needs an object that provides the lock.

There are 2 scenarios where synchronized statements would be useful.

  1. When we are working with third party libraries which are not multi-threaded and we don't have access to source code then synchronized statement blocks could be used to achieve thread safety.
  2. Synchronized statements are also useful for improving concurrency with fine-grained synchronization where the entire method need not be synchronized but only certain lines of the method.

public class ThreadSync {

 class MyCounter {
  private int count = 0;
  private Object lock = new Object();
  MyCounter() {}
  public void increment() {
   synchronized(lock) {
    count = count + 1;
   }
  }
 }
 
 class MyThread extends Thread {
  MyCounter counter = null;
  MyThread(MyCounter counter) {
   this.counter = counter;
  }
  public void run() {
   counter.increment();
  }
 }
 
 public static void main(String[] args) {
  ThreadSync ts = new ThreadSync();
  MyCounter counter = ts.new MyCounter();
  Thread t1 = ts.new MyThread(counter);
  Thread t2 = ts.new MyThread(counter);
  t1.start();
  t2.start();
 }
}

Reentrant synchronization

Consider an example of a synchronized method which is called recursively by a thread. In this case the thread acquires the lock which it already owns. Allowing a thread to acquire the same lock more than once is called re-entrant synchronization.

Contact Form

Name

Email *

Message *

Back to Top