In a multithreaded Java program, where multiple threads are working on individual tasks, an issue can arise when one thread updates a variable, but other threads fail to see the updated value, which can lead to inconsistent data across threads, logic errors, race conditions, incorrect program output, and so on. To solve this problem, the volatile keyword in Java comes into play. It makes sure that all the threads always see the latest value of a shared variable, just like updating a public display for everyone to read. This helps avoid bugs caused by old or hidden values. But does volatile solve all concurrency problems? In this article, we will learn the Volatile keyword in Java in detail.
Table of Contents:
What is a Volatile Keyword in Java?
The volatile keyword in Java is used to indicate that a variable may be accessed and modified by multiple threads. When a variable is declared volatile, it informs the JVM that the variable should not be cached locally by any thread and must always be read from and written to the main memory, which ensures that all threads see the most updated value.
For example, you are building a banking application that logs out the user after a period of inactivity. For that, you have to create a background thread that waits and checks for the activity of the user. If the user clicks “Logout” or becomes inactive for some fixed amount of time, the thread should stop waiting and end the session. For this, you want a shared flag between the main thread and the background thread (inactivity) that tells you to stop waiting and exit. However, both threads are accessing the same variable, so there is a risk that the background thread might not see the updated value due to the thread reading a cached copy instead of the main memory.
To solve this, you can declare the flag as volatile, which will ensure that any change to the flag by one thread (like clicking “Logout”) is immediately visible to the other thread (the inactivity checker).
Master Java Today - Accelerate Your Future
Enroll Now and Transform Your Future
Syntax of Volatile Keyword in Java
The following is the syntax of the volatile keyword in Java:
volatile dataType variableName;
For example,
public class MyClass {
private volatile boolean a; //here is the volatile keyword
}
In the above example,
- MyClass is the name of the Java class
- a is the variable name having the datatype boolean
- private is the access modifier
When to Use the Volatile Keyword in Java?
The volatile keyword in Java can be used with both primitive data types (like int, boolean, float) and object references, i.e., when a variable is declared volatile, this keyword informs the Java Virtual Machine (JVM) that the value of this variable should never be stored in cache memory by any thread. Instead, every thread should always read its most updated value directly from the main memory, which is important in multithreading, where one thread might update a variable while another thread is reading it. Without a volatile keyword, a thread could read an outdated or cached value and behave incorrectly.
By using the volatile keyword in Java, you also ensure the visibility of the variable, which means all the threads see only the latest value of that variable. Additionally, it also provides ordering guarantees of the variable, i.e., the Volatile prevents specific kinds of memory reordering, not all instruction reordering. This also prevents unexpected bugs that are caused by executing the code in a different order than when writing.
Consider the following two examples below, which show the importance of the volatile keyword in Java when working with shared variables across threads. The first example does not use volatile, which can lead to unexpected behavior due to thread-local caching. The second example uses the volatile keyword, ensuring proper visibility of changes between threads. These examples clearly illustrate how the volatile keyword helps avoid subtle concurrency bugs.
Example 1: Without the Volatile Keyword
Output:
Explanation: The above Java program does not use the volatile keyword, due to which the program runs endlessly, because the value of the variable running is not updated to false.
Note: The thread may never stop because it caches the running value and doesn’t see the change made by the main thread. But the output can vary if the JVM takes the value of the variable from the cache.
Example 2: With the Volatile Keyword
Output:
Explanation: In the above Java program, the variable running is declared as volatile, due to which the thread directly takes the updated value of it from the main memory, hence it does not run forever.
Get 100% Hike!
Master Most in Demand Skills Now!
Volatile vs Synchronized in Java
Before learning the difference between the Volatile and Synchronized keywords in Java, let us discuss the concept of Atomicity.
Atomicity means an operation is done completely or not at all, with no interruption in between. Like, turning a light switch ON is an atomic operation, i.e., you either switch the light ON or OFF, there is no halfway state.
1. Volatile Keyword in Java
The volatile keyword in Java is used to mark a variable as visible to all the threads. When a variable is declared volatile, it tells the JVM that no thread should cache its value locally, and all the read or write operations must go directly to the main memory. It is mainly used for simple flags or status variables, and it does not guarantee atomicity.
Example:
Output:
Explanation: In the above Java program, two threads t1 and t2 are started, and each thread calls the increment() method 1000 times, a total of 2000 expected increments. The volatile keyword ensures that every read or write operation goes to the main memory, not the cached thread memory. So, when thread 1 changes the counter, thread 2 will see the updated value.
2. Synchronized Keyword in Java
On the other hand, the Synchronized keyword in Java is used to provide a mutual exclusion property to the thread, which ensures that only one thread can execute a block of code or method at a time, locking either an object or a class. It guarantees both visibility and atomicity. This means that while volatile
keyword ensures every thread sees the latest value of a shared variable, but the actions within the synchronized block are executed safely and exclusively by one thread at a time.
Example:
Output:
Explanation: In the above Java program, two threads t1 and t2 again increment the counter 1000 times, and the increment() method is marked synchronized. The Synchronized keyword puts a lock on the method increment(), and only one thread at a time can execute increment() on the same object. So, the counter++ operation becomes atomic and thread-safe. Hence, the result always comes as 2000, no matter how many times the program is executed.
Now, let us discuss the difference between the volatile and synchronized keywords in Java.
Feature |
Volatile |
Synchronized |
Visibility |
Yes |
Yes |
Atomicity |
No |
Yes |
Prevents race conditions |
No |
Yes |
Lightweight |
Yes (no locking) |
Slightly slower due to locking |
Volatile Keyword in Java vs C/C++
Both Java and C/C++ have a volatile keyword, but they behave differently, especially in how they deal with memory visibility, thread safety, and compiler optimizations.
Feature |
Java (volatile) |
C/C++ (volatile) |
Purpose |
Make sure all threads see the latest value of a variable. |
Stops the compiler from removing memory access to a variable. |
Caching |
Tells threads not to use cached values |
Tells the compiler not to store the variable in a register or cache. |
Memory behavior |
Every read/write happens in the main memory, so all threads stay updated. |
Used to make sure hardware devices or interrupts are read or written as they are. |
Where it’s used |
For multi-threaded programming |
For embedded systems |
Compiler optimizations |
Stops Java from reordering or skipping memory operations for this variable. |
Stops C/C++ compiler from removing or reordering memory accesses. |
Memory reordering |
Prevents both the Java compiler and CPU |
Only stops the compiler, not the CPU |
Unlock Your Future in Java
Start Your Java Journey for Free Today
Best Practices for Using Volatile Keyword in Java
Some common errors can occur when using the volatile keyword in Java. To prevent this, some common practices should be followed, which are discussed below:
- Do not use volatile for compound actions like x++ or count += 1 because they read the current value, make a change in it, and then write it back, hence, they can lead to incorrect results.
- Use the volatile keyword with boolean flags, as it is effective when it is used with simple boolean flags because these variables control the working of a thread, i.e., they control when it should start or stop.
- Do not use the volatile keyword unnecessarily, as this can lead to confusion in the code and affect performance, because the variable must be read from the main memory each time, instead of being accessed from the thread-local cache.
Advantages of Volatile Keyword in Java
The following are the advantages of the volatile keyword in Java:
- It is perfect for simple use cases like stop signals, readiness flags, or session status variables, mainly when there is only one writer thread
- When a variable is declared as volatile, any change made by one thread is immediately visible to all the other threads.
- The volatile keyword in Java is faster and lighter than using synchronized blocks or locks.
Disadvantages of Volatile Keyword in Java
The following are the disadvantages of the volatile keyword in Java:
- While volatile is a lightweight keyword, its frequent usage can lead to performance issues as the variable has to access the main memory to read the value of the variable.
- The volatile keyword cannot be used when you need mutual exclusion, such as when multiple threads must access a shared block of code safely and exclusively.
- It only works for individual variables; if you have to manage the consistency across multiple fields or operations, you must use the synchronized keyword.
Conclusion
From the above article, we learned that the volatile keyword in Java is a tool used for multithreading, to ensure that the latest value of a variable is always visible to all the threads. It helps prevent issues caused by thread-local caching and memory reordering. However, it does not guarantee the property of atomicity and is suitable only for simple flags and single-write variables. For more complex operations, you should use synchronization or atomic classes. Unlike Java, C/C++ uses volatile mainly to prevent compiler optimizations for hardware-related programming, but it does not ensure thread safety. Therefore, volatile serves different purposes in Java and C/C++.
If you want to learn more about Volatile Keyword in Java, you can refer to our Java Course.
Volatile Keyword in Java – FAQs
Q1. Is volatile thread-safe in Java?
No, the volatile keyword only ensures visibility between the threads, not atomicity. It is thread-safe only for simple flags, not for compound actions.
Q2. What are the volatile and transient keywords in Java?
The volatile keyword in Java makes sure that all the threads see the latest value of a variable. The transient keyword prevents a field from being saved during the process of serialization.
Q3. Why use volatile in singleton Java?
Volatile is used to ensure the instance of the class is visible correctly across all the threads, preventing the use of a partially constructed object.
Q4. When should I use synchronized Java?
Use synchronized keywords when you have to ensure that only one thread can access a block of code at a time, mainly for atomic operations or updating shared data safely.
Q5. How is volatility used in the Singleton pattern?
Volatile ensures that the instance reference is visible correctly to all threads, avoiding issues like partially constructed objects during double-checked locking.