In Java, the volatile keyword is used as a modifier for instance variables to indicate that their value may be modified by multiple threads concurrently. It ensures proper visibility and ordering of variable reads and writes in a multithreaded environment.
Key Aspects of the volatile Keyword
1. Visibility Guarantee
- When a variable is declared
volatile, any write to it by one thread is immediately visible to all other threads. - Without
volatile, threads may cache variables locally, leading to stale data.
2. No Thread-Local Caching
- The JVM ensures that the value of a
volatile variable is always read from the main memory, not from a thread's local cache.
3. Atomic Read and Write (but not Compound Operations)
- The
volatile keyword guarantees that reads and writes are atomic. - However, compound actions like
count++ are not atomic and must be protected with synchronization or atomic classes.
4. Lightweight Alternative to Synchronization
- Unlike
synchronized, volatile does not involve locking, making it more lightweight and performant for simple read/write operations.
5. Use Cases
The volatile keyword is suitable when:
- Only one thread modifies the variable, and others read it.
- There are no compound actions or multiple-variable dependencies.
- Visibility is the primary concern, not mutual exclusion.
Example:
java
class SharedResource {
private volatile boolean flag = false;
public void setFlagTrue() {
flag = true;
}
public boolean isFlagTrue() {
return flag;
}
}
In this example, the flag variable is declared as volatile so that when one thread sets it to true, other threads can immediately see that change without delay.
Important Note:
While volatile is useful for visibility in simple cases, it does not replace synchronized or other thread-safety mechanisms for complex operations. For compound actions or managing consistency across multiple variables, consider using synchronization or classes from the java.util.concurrent package like AtomicInteger or ReentrantLock.