Volatile keyword in Java


Java Thread VolatileViews 1840

Volatile keyword in Java

In a multithreading environment, there are several situations where multiple threads try to update the same shared variable. This means it can lead to concurrency issues in Java. To handle this and make it thread-safe, we can use the volatile keyword in Java to update the shared variables.

We can use the volatile keyword for either primitive data types or objects. Also, we can use it only for variables and not for methods or classes. Volatile variables always read and write the data directly from the main memory. It ensures the right ordering and visibility of variables.

Concurrency issue without volatile

Imagine we have 2 threads T1 and T2 that use the same shared variable var and the computer has multiple CPUs for better performance. When we do not declare this variable as volatile, both the threads can read and write the var variable into its own CPU cache and do not update the main memory. In this way, each thread has its own variable copy in the corresponding cache whereas a different value in the main memory. This can lead to incorrect variable updates when both threads try to read and update the same variable at a time. It is another concurrency issue in Java.

The below diagram explains the above issue clearly. This issue is called the variable visibility problem.

Java concurrency

Solving visibility issue

Now, let us see how the volatile variable solves the visibility issue. Whenever we write or update the value for a volatile variable, it immediately writes it back to the main memory. Also, all threads are allowed to read these variable values only directly from the main memory. In this way, one thread updates the value and the other thread reads the same variable, both the threads will read the same updated variable value. This is because the thread updates the value immediately in the main memory so that other threads can read the value from the main memory.

Volatile keyword in Java

Below is the syntax of declaring a volatile variable.

public volatile int var = 5;

Suppose, both the threads want to update the shared variable, then the volatile keyword is not sufficient. For this, we have to use the synchronized keyword which we will discuss in a separate tutorial.

Use of volatile keyword

  • Use volatile keywords when there is 1 thread to update the variable and multiple threads to read the variable. In this way, all the other threads will read the same value otherwise each may read a different value.
  • It is another method of implementing synchronization in java.
  • Prevents reordering of the code and avoids writing the value in the cache memory instead of the main memory.
  • We can use the volatile keyword only for variables and not for classes or methods.
  • Volatile variables perform atomic action which means when a thread starts any operation, other threads can perform an action on the same variable only when the previous thread completes it.
  • A volatile variable is required only for shared variables. It is not required to declare volatile when multiple threads are not accessing the same variable.

Example of volatile keyword in Java

Below is an example of using a java volatile keyword for a counter variable where 1 thread updates the value and the other thread reads the value. Since we have used the volatile keyword after the write thread completes its action, it executes the read thread and then again continues the execution. This solves the concurrency issue in Java.

public class VolatileDemo {
  private static volatile int val = 0;

  public static void main(String[] args) {
    new readData().start();
    new writeData().start();

  }
  
  static class readData extends Thread {
    public void run() {
      int num = val;
      while(num < 3) {
        if(num != val) {
          System.out.println("New Value: " + val);
          num = val;
        }
      }
    }
  }
  
  static class writeData extends Thread {
    public void run() {
      int num = val;
      while(val < 3) {
        System.out.println("Increment value: " + (num+1));
        val = ++num;
        try {
          Thread.sleep(200);
        }
        catch(Exception e) {
          e.printStackTrace();
        }
      }
    }
  }

}


Increment value: 1
New Value: 1
Increment value: 2
New Value: 2
Increment value: 3
New Value: 3

Suppose, we don’t use the java volatile keyword, then the output will be as below and the writeData thread executes infinitely.

Increment value: 1
New Value: 1
Increment value: 2
Increment value: 3

Difference between volatile and synchronized keyword

Below are the differences between the volatile keyword in Java and the synchronized keyword.

volatile keywordsynchronized keyword
It can be used only for variablesIt can be used for variables, methods and code blocks
We cannot block a waiting threadWe can block a waiting thread
Improves thread performanceDegrades thread performance
Does not allow compiler optimizationAllows compiler optimization
Synchronizes the value of only 1 variable at a timeSynchronizes the value of all variables at a time

Reference

Translate ยป