Java volatile Keyword

The volatile keyword in Java is used to indicate that a variable’s value will be modified by different threads. It ensures that changes made to a variable in one thread are immediately visible to other threads, thus providing a lightweight synchronization mechanism.

Table of Contents

  1. Introduction
  2. volatile Keyword Syntax
  3. Understanding volatile
  4. Examples
    • Volatile Variable
    • Volatile vs Synchronized
  5. Real-World Use Case
  6. Conclusion

Introduction

In multithreaded programming, it is crucial to ensure that the latest value of a shared variable is always visible to all threads. The volatile keyword helps achieve this by instructing the Java Virtual Machine (JVM) to always read the variable from the main memory and not from a thread’s local cache.

volatile Keyword Syntax

The syntax for declaring a volatile variable is straightforward:

volatile dataType variableName;

Example:

volatile boolean flag;

Understanding volatile

Key Points:

  • Visibility: Changes to a volatile variable are always visible to other threads.
  • No Caching: A volatile variable is not cached locally in any thread; it is always read from and written to main memory.
  • Atomicity: Operations on volatile variables are atomic only for single read/write operations. Complex operations like incrementing a variable are not atomic and require additional synchronization.

Examples

Volatile Variable

A simple example demonstrating the use of a volatile variable to ensure visibility across threads.

Example

public class VolatileExample {
    private volatile boolean flag = true;

    public void stop() {
        flag = false;
    }

    public void run() {
        while (flag) {
            // Do some work
        }
        System.out.println("Thread stopped.");
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileExample example = new VolatileExample();

        Thread thread = new Thread(example::run);
        thread.start();

        Thread.sleep(1000);
        example.stop();

        thread.join();
        System.out.println("Main thread finished.");
    }
}

Output:

Thread stopped.
Main thread finished.

Volatile vs Synchronized

A comparison between volatile and synchronized for a counter example.

Example

public class VolatileVsSynchronized {
    private volatile int volatileCounter = 0;
    private int synchronizedCounter = 0;

    public void incrementVolatileCounter() {
        volatileCounter++;
    }

    public synchronized void incrementSynchronizedCounter() {
        synchronizedCounter++;
    }

    public int getVolatileCounter() {
        return volatileCounter;
    }

    public int getSynchronizedCounter() {
        return synchronizedCounter;
    }

    public static void main(String[] args) throws InterruptedException {
        VolatileVsSynchronized example = new VolatileVsSynchronized();

        Runnable volatileTask = () -> {
            for (int i = 0; i < 1000; i++) {
                example.incrementVolatileCounter();
            }
        };

        Runnable synchronizedTask = () -> {
            for (int i = 0; i < 1000; i++) {
                example.incrementSynchronizedCounter();
            }
        };

        Thread thread1 = new Thread(volatileTask);
        Thread thread2 = new Thread(volatileTask);
        Thread thread3 = new Thread(synchronizedTask);
        Thread thread4 = new Thread(synchronizedTask);

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();

        thread1.join();
        thread2.join();
        thread3.join();
        thread4.join();

        System.out.println("Volatile Counter: " + example.getVolatileCounter());
        System.out.println("Synchronized Counter: " + example.getSynchronizedCounter());
    }
}

Output:

Volatile Counter: 1865
Synchronized Counter: 2000

The volatile counter may not reach 2000 due to race conditions, while the synchronized counter reliably reaches 2000.

Real-World Use Case

Flag for Stopping Threads

In real-world applications, volatile is commonly used for flags that signal threads to stop running.

Example

public class StopThreadExample {
    private volatile boolean running = true;

    public void stop() {
        running = false;
    }

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

    public static void main(String[] args) throws InterruptedException {
        StopThreadExample example = new StopThreadExample();

        Thread thread = new Thread(example::run);
        thread.start();

        Thread.sleep(1000);
        example.stop();

        thread.join();
        System.out.println("Main thread finished.");
    }
}

Output:

Thread stopped.
Main thread finished.

Conclusion

The volatile keyword in Java is used for ensuring the visibility of changes to variables across threads. It provides a simple way to achieve thread safety for certain types of variables without the overhead of synchronization. However, it is important to understand its limitations and use it appropriately in conjunction with other synchronization mechanisms when necessary.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top