Java volatile Keyword
Usage and Examples

volatile Keyword in Java

In Java, the volatile keyword is used with variables to indicate that the value of a variable will be modified by different threads. It's a part of Java's memory management model and is crucial for safe access to shared variables in a concurrent application.

Why Do We Need volatile?

Java threads may cache variables locally to improve performance. However, this can lead to situations where one thread doesn't see the most recent value of a variable modified by another thread.

By declaring a variable volatile, we tell the JVM:

  • Do not cache the value locally.
  • Always read it from and write it to the main memory.

How volatile Works

Let’s understand this with a simple example. Consider a boolean flag that controls whether a thread should continue running or not.

public class VolatileDemo extends Thread {
    private volatile boolean running = true;

    public void run() {
        System.out.println("Thread started...");
        while (running) {
            // do work
        }
        System.out.println("Thread stopped.");
    }

    public void stopThread() {
        running = false;
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileDemo thread = new VolatileDemo();
        thread.start();

        Thread.sleep(1000);
        thread.stopThread(); // this will be seen by the other thread due to volatile
    }
}
Thread started...
Thread stopped.

Without volatile: What Goes Wrong?

If the running variable is not marked volatile, the thread might not stop as expected because it could be using a cached version of the variable that never sees the update.

Key Characteristics of volatile

  • Visibility: Ensures the updated value is visible to all threads.
  • No atomicity: It doesn’t make compound actions (like count++) atomic.
  • No locking: Unlike synchronized, it doesn’t use locks, hence it's lightweight and faster.

Common Use Cases for volatile

  • Flags for stopping threads.
  • Status or state monitoring variables.
  • Double-checked locking (used with care).

Example: Visibility Without Synchronization

This demonstrates the difference volatile makes.

public class WithoutVolatile {
    private static boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        new Thread(() -> {
            while (!flag) {
                // busy wait
            }
            System.out.println("Flag detected as true!");
        }).start();

        Thread.sleep(1000);
        flag = true; // may not be visible to other thread
    }
}
(no output - thread is stuck in infinite loop)

Now change flag to volatile and you’ll see:

Flag detected as true!

Difference Between volatile and synchronized

Aspect volatile synchronized
Guarantees Visibility Yes Yes
Guarantees Atomicity No Yes
Performance Faster Slower (due to locking)
Use Case Simple flags or state sharing Complex critical sections

Can You Use volatile for Counters?

No. If you try to use volatile for increment operations like count++, it won't be thread-safe because ++ is not an atomic operation. Use AtomicInteger or synchronization instead.

private volatile int count = 0;

public void increment() {
    count++; // not thread-safe!
}