Table of Contents
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.
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.
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 keyword | synchronized keyword |
---|---|
It can be used only for variables | It can be used for variables, methods and code blocks |
We cannot block a waiting thread | We can block a waiting thread |
Improves thread performance | Degrades thread performance |
Does not allow compiler optimization | Allows compiler optimization |
Synchronizes the value of only 1 variable at a time | Synchronizes the value of all variables at a time |