Skip to main content
Documents
Share
LinkedIn
Facebook
Twitter
Copy
Java keywords

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 volatile to 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: volatile does not guarantee atomicity. For compound actions (e.g., increment operations), consider using other synchronization mechanisms like synchronized blocks or AtomicInteger.
    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 volatile can lead to performance issues. Use it only when necessary to ensure visibility.
  • Combine with Other Synchronization: In complex scenarios, combine volatile with other synchronization mechanisms to ensure both visibility and atomicity.
    private volatile boolean flag = false;
    
    synchronized (this) {
        flag = true;
    }
  • Memory Consistency: The volatile keyword helps prevent memory consistency errors by establishing a happens-before relationship, ensuring that changes to a volatile variable are visible to other threads.