Volatile vs Synchronized in Java

In this article, we will discuss volatile vs synchronized in Java.

First, we will define what is synchronized.

Synchronized Keyword

Synchronized is the keyword which is applied on blocks and methods but not on the classes and variables. When multiple threads are trying to access the same Java object so this situation leads to a data inconsistency problem. So in this situation, we should go for a synchronized keyword.

So we use synchronized keywords along with the name of the method declaration only so that if that method is accessing the Java object no other thread can access that object because synchronized methods hold a lock on that object. When it will do its processing and completes its task then the lock can be unlocked and can be used by other threads.

The biggest merit of using synchronized keywords is that we can overcome inconsistent state or can overcome inconsistency problems whereas the biggest demerit is that due to the lock to the object it may lead to performance issues.

SynchronizedSyntax:

synchronized(objectidentifier)

{

// Access shared variables and other shared resources
}

Program:

class SynchronizedData

{
    public void printCount() 
    {
       int j;
       try
       {
         for( j = 5; j > 0; j--)
         {
            System.out.println("Counter --- " + j );
         }
       }

      catch (Exception e)
      {
        System.out.println("Thread interrupted.");
      }
   }
}

class SynchronizedThread extends Thread
{
   private Thread t;
   private String threadName;
   SynchronizedData PD;

   SynchronizedThread( String name, SynchronizedData pd) 
   {
     threadName = name;
     PD = pd;
   }

    public void run()
    {
       PD.printCount();
       System.out.println("Thread " + threadName + " exiting.");
    }

    public void start ()

    {
      System.out.println("Starting " + threadName );
      if (t == null)
      {
        t = new Thread (this, threadName);
        t.start ();
     }
   }
}

public class SynchronizedMain

{
  public static void main(String args[])
  {

    SynchronizedData PD = new SynchronizedData();

    SynchronizedThread T1 = new SynchronizedThread( "Thread - 1 ", PD );
    SynchronizedThread T2 = new SynchronizedThread( "Thread - 2 ", PD );

    T1.start();
    T2.start();

    // wait for threads to end
    try
    {
       T1.join();
       T2.join();
    }

    catch ( Exception e)
    {
      System.out.println("Interrupted");
    }
  }
}

Output:

Starting Thread - 1
Starting Thread - 2
Counter --- 5
Counter --- 4
Counter --- 5
Counter --- 4
Counter --- 3
Counter --- 2
Counter --- 1
Counter --- 3
Counter --- 2
Counter --- 1
Thread Thread - 2 exiting.
Thread Thread - 1 exiting.

Now, we will talk about volatile keywords.

Volatile Keyword

So basically the variable values are changed by different threads running concurrently and that value is changed i.e read and write on CPU cache which may lead to inconsistency. To avoid this problem we have a volatile modifier which is related to the visibility of the variable that is each variable value is read and write by threads running concurrently in the RAM itself instead of CPU cache.

Every change made by the threads shall take place in the local copy only so that the impact of the change will not take place in other threads. This will overcome the problem of inconsistency. Hence maintaining the separate copy for each thread may result in increasing the complexity of the program which is the demerit of this.

Volatile

Syntax:

class VolatileData
{
    static volatile int var = 5;
}

Program:

public class VolatileData
{
   private static volatile int MY_INT = 0;
   public static void main(String[] args)
   {

      ChangeMaker changeMaker = new ChangeMaker();
      changeMaker.start();

      ChangeListener changeListener = new ChangeListener();
      changeListener.start();

   }

   static class ChangeMaker extends Thread 
   {

     @Override
     public void run() 
     {
        while (MY_INT < 5)
        {
          System.out.println("Incrementing MY_INT "+ ++MY_INT);
          try
          {
              Thread.sleep(1000);
          }
          catch(InterruptedException exception) 
          {
            exception.printStackTrace();
          }
       }
   }
}

static class ChangeListener extends Thread 
{

  int local_value = MY_INT;
  @Override
  public void run() 
  {
    while ( MY_INT < 5)
    {
      if( local_value!= MY_INT)
      {
        System.out.println("Got Change for MY_INT "+ MY_INT);
        local_value = MY_INT;
      }
    }
  }
}

}

Output:

Incrementing MY_INT 1

Incrementing MY_INT 2

Got Change for MY_INT 2

Incrementing MY_INT 3

Got Change for MY_INT 3

Got Change for MY_INT 4

Incrementing MY_INT 4

Got Change for MY_INT 5

Incrementing MY_INT 5

Volatile vs Synchronized

Synchronized Volatile
Synchronized keywords apply only to methods and blocks. Volatile apply only to variables. If we will try to apply volatile keywords along with the method then the compiler will show an error.
Synchronized keyword uses lock-based algorithms to lock those methods and blocks. Volatile implements a non-blocking algorithm that is more scalable.
Due to the acquisition and release of lock, the performance is slower in the synchronized keywords. Volatile is much better than synchronized in terms of performance.
Synchronized keyword follows locking approach due to which deadlocks and livelock may occur. Volatile does not follow this approach so it is free to deadlock and livelock.
Synchronized fields are part of compiler optimization. Volatile fields are not part of compiler optimization.

Conclusion

Both Synchronized and Volatile have their own merits and demerits therefore it is advised to use it in a very strict format (i.e. according to the specific requirements).

So, that’s all about volatile vs synchronized in Java.

Leave a Comment

Your email address will not be published. Required fields are marked *