Thread Synchronization and Synchronized Block in Java

Multi-threading in java is a vast topic. I have already shared frequently asked interview questions on multi-threading. In this post we will learn about what is synchronization and synchronized block in java in detail. So let's start by understanding the term "Synchronization" first. 

Read Also :  Multi-threading Interview Questions

What is Synchronization?

Synchronization in java is a technique to prevent concurrent access of any shared resource in a multi-threaded environment.

Why Synchronization?

In multi-threaded environment, we may come across a situation where two or more threads try to gain access to the same resource and try updating it. This may lead to unexpected outcomes, inconsistencies and errors.
Therefore, it becomes important that one and only one thread should access such a resource at any given point of time and this is achieved by thread synchronization. It is important to note that if the shared resource is mutable and multiple threads are accessing it, then only synchronization is required. In case of immutable or read only objects, synchronization is not required as there will be no change to the state of the object.

Thread synchronization can be achieved using different strategies like using synchronized methods, synchronized blocks and inter-thread communication. In this article, we will discuss only about synchronized blocks in Java.

Multi-threading without Synchronization:

Let’s first see the below example where two threads are trying to access the same method of the shared object in an unsynchronized way.

package com.javahungry;

class Counter {
 void printValue(String threadName) {
  for (int i = 1; i <= 5; i++) {
   System.out.println(threadName +  
                        " with counter value --> " + i);
   try {
    Thread.sleep(200);
   } 
   catch (InterruptedException e) {
    System.out.println("Thread interrupted.");
   }
  }
 }
}

public class NotSynchronizedDemo {

 public static void main(String[] args) {

  final Counter counter = new Counter();
  Thread t1 = new Thread("Thread 1") {
   public void run() {
    counter.printValue(Thread.currentThread().getName());
   }
  };

  Thread t2 = new Thread("Thread 2") {
   public void run() {
    counter.printValue(Thread.currentThread().getName());
   }
  };

  t1.start();
  t2.start();
 }

}

Output:

Thread 1 with counter value --> 1
Thread 2 with counter value --> 1
Thread 1 with counter value --> 2
Thread 2 with counter value --> 2
Thread 2 with counter value --> 3
Thread 1 with counter value --> 3
Thread 1 with counter value --> 4
Thread 2 with counter value --> 4
Thread 2 with counter value --> 5
Thread 1 with counter value --> 5

As it is evident from above output, both of the threads have unsynchronized concurrent access to the shared method. The threads do not wait for the other thread to finish its execution and enter the common piece of code. This results in thread interference which can lead to data corruption and inconsistency. We will now see how to prevent this using java synchronized block.

Synchronized block:

A piece of code marked with synchronized keyword is known as Synchronized block. The shared resources that need to be synchronized are placed inside it to prevent concurrency related issues in case of multithreading. Java uses concept of monitors to achieve synchronization. Every object in Java has an associated monitor which can be locked or unlocked by a thread.

Syntax:

synchronized(objectReference){

//the code goes here 

}

The argument in parentheses is called monitor object and the code is synchronized on this object. Only one thread can obtain a lock on this monitor object at any given point of time. The synchronized block may throw NullPointerException if the monitor object passed as the argument to the synchronized block is null.

Synchronized block inside instance method:

The term “synchronized block” normally applies to synchronized block inside instance method. It is used to synchronize a block of code inside a non-static method.

Example:

public void displayCount(int count) {

 //synchronized block starts
        synchronized (this) 
        {
             count++;
             System.out.println(count);
 }
 //synchronized block ends

}

The instance which invokes the method having synchronized block is the monitor object and its lock is associated with the monitor. This instance has been denoted by “this” keyword in the above example. Only one thread will be able to execute the code inside synchronized code block for the same monitor object.

Multithreading using synchronized block inside instance method:


package com.javahungry;

class Counter {
 void printValue(String threadName) {
  synchronized (this) {
   for (int i = 1; i <= 5; i++) {
    System.out.println(threadName +  
                                " with counter value --> " + i);
    try {
     Thread.sleep(200);
    } 
    catch (InterruptedException e) {
     System.out.println("Thread interrupted.");
    }
   }
  }
 }
}

public class SynchronizedDemo {

 public static void main(String[] args) {

  final Counter counter = new Counter();
  Thread t1 = new Thread("Thread 1") {
   public void run() {
    counter.printValue(Thread.currentThread().getName());
   }
  };

  Thread t2 = new Thread("Thread 2") {
   public void run() {
    counter.printValue(Thread.currentThread().getName());
   }
  };

  t1.start();
  t2.start();
 }

}


Output:

Thread 1 with counter value --> 1
Thread 1 with counter value --> 2
Thread 1 with counter value --> 3
Thread 1 with counter value --> 4
Thread 1 with counter value --> 5
Thread 2 with counter value --> 1
Thread 2 with counter value --> 2
Thread 2 with counter value --> 3
Thread 2 with counter value --> 4
Thread 2 with counter value --> 5

As we can see from the result above, Thread 1 starts its execution and once it finishes only then Thread 2 starts executing. Keeping the code inside synchronized block has solved the problem that we faced when the same block of code was not synchronized and we got inconsistent output.

Synchronized block inside static method:

It is also known as static synchronization and is used to synchronize the code block inside a static method.

Example:
 
public static void displayCount(int count) {
  
  //synchronized block inside static starts
  synchronized (Counter.class) {
   count++;
   System.out.println(count);
  }
  //synchronized block inside static ends
 }

In case of synchronized block inside a static method, the monitor object is the class itself. We pass .class as the argument for the synchronized block in this case. In case of multiple instances of a class, only one thread can execute the code inside synchronized block in any of the available instances of such a class. This is called Class level locking and is done to keep static information thread safe.

Multithreading using synchronized block inside static method:


package com.javahungry;

class Counter {
 static void printValue(String threadName) {
  synchronized (Counter.class) {
   for (int i = 1; i <= 5; i++) {
    System.out.println(threadName + 
                                " with counter value --> " + i);
    try {
     Thread.sleep(200);
    } 
    catch (InterruptedException e) {
     System.out.println("Thread interrupted.");
    }
   }
  }
 }
}

public class StaticSynchronizedDemo {

 public static void main(String[] args) {

  Thread t1 = new Thread("Thread 1") {
   public void run() {
    Counter.printValue(Thread.currentThread().getName());
   }
  };

  Thread t2 = new Thread("Thread 2") {
   public void run() {
    Counter.printValue(Thread.currentThread().getName());
   }
  };

  t1.start();
  t2.start();
 }

}

Output:

Thread 1 with counter value --> 1
Thread 1 with counter value --> 2
Thread 1 with counter value --> 3
Thread 1 with counter value --> 4
Thread 1 with counter value --> 5
Thread 2 with counter value --> 1
Thread 2 with counter value --> 2
Thread 2 with counter value --> 3
Thread 2 with counter value --> 4
Thread 2 with counter value --> 5

From the above results, it is evident that the threads are processing the code in a synchronized way in case of static method having synchronized block inside it. At a time, one thread gets access to the synchronized code inside printValue() method, it executes the logic while the other thread waits. Once the first thread to enter the synchronized logic finishes its execution, the next thread get the access and starts it execution.

That's all for the post thread synchronization and synchronized block in java. Please mention in the comments in case you have any questions.

Reference :
Java Synchronization doc

About The Author

Subham Mittal has worked in Oracle for 3 years.
Enjoyed this post? Never miss out on future posts by subscribing JavaHungry