volatile Keyword in Java
The volatile keyword in Java is used to indicate that a variable's value will be modified by different threads. It ensures that changes to a variable are always visible to other threads, preventing thread caching issues.
Usage
The volatile keyword is primarily used in multi-threaded programming to ensure that a variable's updates are propagated predictably across threads.
Syntax
volatile dataType variableName;
dataType: The type of the variable (e.g.,int,boolean, etc.).variableName: The name of the variable.
Examples
Example 1: Basic Usage
public class VolatileExample extends Thread {
private volatile boolean running = true;
public void run() {
while (running) {
// Thread is running
}
System.out.println("Thread stopped.");
}
public void stopRunning() {
running = false;
}
public static void main(String[] args) throws InterruptedException {
VolatileExample thread = new VolatileExample();
thread.start();
Thread.sleep(1000);
thread.stopRunning();
thread.join();
}
}
In this example, the running variable is marked as volatile. The run method checks the running variable in a loop. The stopRunning method sets running to false, which stops the loop. The volatile keyword ensures that changes to running are immediately visible to the run method.
Example 2: Volatile with Multiple Threads
public class VolatileCounter {
private volatile int counter = 0;
public void increment() {
counter++;
}
public int getCounter() {
return counter;
}
public static void main(String[] args) throws InterruptedException {
VolatileCounter vc = new VolatileCounter();
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
vc.increment();
}
};
Thread t1 = new Thread(task);
Thread t2 = new Thread(task);
t1.start();
t2.start();
t1.join();
t2.join();
System.out.println("Counter value: " + vc.getCounter());
}
}
In this example, the counter variable is marked as volatile. Two threads increment the counter variable concurrently. The volatile keyword ensures that each thread sees the most recent value of counter.
Tips and Best Practices
- Visibility Guarantee: Use
volatileto ensure visibility of changes to variables across threads. It guarantees that a read of a volatile variable always returns the most recent write by any thread. - Atomicity:
volatiledoes not guarantee atomicity. For compound actions (e.g., increment operations), consider using other synchronization mechanisms likesynchronizedblocks orAtomicInteger.private AtomicInteger counter = new AtomicInteger(0); counter.incrementAndGet(); - Use Cases: Appropriate for flags, state variables, and other variables where the latest value is critical but compound operations are not required.
- Avoid Overuse: Overusing
volatilecan lead to performance issues. Use it only when necessary to ensure visibility. - Combine with Other Synchronization: In complex scenarios, combine
volatilewith other synchronization mechanisms to ensure both visibility and atomicity.private volatile boolean flag = false; synchronized (this) { flag = true; } - Memory Consistency: The
volatilekeyword helps prevent memory consistency errors by establishing a happens-before relationship, ensuring that changes to a volatile variable are visible to other threads.