volatile keyword

In Java, the volatile keyword is used to indicate that a variable’s value may be changed by multiple threads, and that all threads should always see the most up-to-date value of that variable.

It’s a key concept in multithreading and concurrency.


🧠 Definition

A volatile variable is one whose reads and writes go directly to main memory, rather than being cached in a thread’s local memory (CPU cache).

Without volatile:

  • Each thread might keep its own cached copy of a variable.
  • Changes made by one thread might not be visible to others immediately.

With volatile:

  • Every read or write goes to main memory.
  • Changes are immediately visible to all threads.

Example Without volatile

class ExampleWithoutVolatile {
    private static boolean running = true;

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (running) {
                // Busy-wait
            }
            System.out.println("Thread stopped");
        });

        t.start();

        Thread.sleep(1000);
        running = false;  // Main thread stops the loop
        System.out.println("Main thread set running = false");
    }
}

❌ Problem:

  • The worker thread might never stop because it keeps reading a cached copy of running that remains true.

Fix Using volatile

class ExampleWithVolatile {
    private static volatile boolean running = true;

    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(() -> {
            while (running) {
                // Busy-wait
            }
            System.out.println("Thread stopped");
        });

        t.start();

        Thread.sleep(1000);
        running = false;  // Immediately visible to the other thread
        System.out.println("Main thread set running = false");
    }
}

✅ Output:

Main thread set running = false
Thread stopped

Now the worker thread sees the updated value.


⚙️ Key Properties of volatile

PropertyDescription
VisibilityAll threads see the most recent value of a volatile variable.
AtomicityOnly reads and writes to volatile variables are atomic (not compound operations).
No lockingDoes not block threads — lighter than synchronized.
Memory barrierPrevents reordering of reads/writes across volatile boundaries (important for the Java Memory Model).

⚠️ Limitations

volatile does not make compound actions atomic.
For example:

volatile int count = 0;

void increment() {
    count++;  // NOT atomic — it’s read, increment, then write
}

Even though count is volatile, two threads could still interleave:

  • Thread A reads 5
  • Thread B reads 5
  • Both write 6 → ❌ one increment lost

✅ To fix that, use:

  • synchronized, or
  • Atomic classes like AtomicInteger.

🧩 When to Use volatile

Use it when:

  • One thread writes to a variable.
  • Other threads only read it.
  • You don’t need atomic compound updates.

✅ Examples:

  • Status flags (e.g., isRunning, shutdownRequested)
  • Configuration changes read by multiple threads
  • Double-checked locking pattern (in combination with synchronization)

💡 Quick Summary

Aspectvolatile
Guarantees visibility✅ Yes
Guarantees atomicity❌ No (except for reads/writes)
Prevents instruction reordering✅ Yes
Use caseShared flags, status indicators
Alternative for atomic updatesAtomicInteger, synchronized

Leave a Reply