DEV Community

Cover image for Using Java’s Volatile Keyword Effectively: A Closer Look
Tharindu Dulshan Fernando
Tharindu Dulshan Fernando

Posted on

Using Java’s Volatile Keyword Effectively: A Closer Look

The volatile keyword in Java is a useful yet sometimes misunderstood tool for concurrent programming. It is essential to ensure that threads may exchange data and communicate properly without encountering problems such as unexpected behaviour or inconsistent data.

We declare a variable named sharedVariable as volatile in the above instance. This implies that any changes made to sharedVariable by one thread will affect all other threads instantly.

volatile int sharedVariable = 0;
Enter fullscreen mode Exit fullscreen mode

We declare a variable named sharedVariable as volatile in the above instance. This implies that any changes made to sharedVariable by one thread will affect all other threads instantly.

Let’s Understand Volatility in Multithreading:

Modern processors carry out improvements such as thread caching, where each thread may store a local copy of a shared variable. Unexpected behaviour may arise from changes to a thread taking longer to propagate.

The Problem of Thread Caching:

public class SharedData {
    private int sharedVariable = 0;

    public void modifyVariable() {
        sharedVariable = 42;
        // Other functions or operations
    }

    public int readVariable() {
        return sharedVariable;
    }
}
Enter fullscreen mode Exit fullscreen mode

In the above example, even if “modifyVariable” is being called by a single thread, changes might not be suddenly visible to other threads reading “sharedVariable”.

After Entering the Volatile Keyword:

public class SharedData {
    private volatile int sharedVariable = 0;

    public void modifyVariable() {
        sharedVariable = 42;
        // rest of the functions or operations
    }

    public int readVariable() {
        return sharedVariable;
    }
}
Enter fullscreen mode Exit fullscreen mode

We make sure any changes performed by one thread will be instantly accessible to all other threads by defining sharedVariable as volatile. The volatile keyword stops the CPU and compiler from doing specific optimizations that can jeopardize visibility.

Example 1: Flagging and Signaling between Threads

public class SharedResource {
    private volatile boolean flag = false;

    public void setFlagTrue() {
        flag = true;
    }

    public void checkFlag() {
        while (!flag) {
            // Busy-wait until the flag becomes true
        }
        System.out.println("Flag is now true. Continuing the execution.");
    }
}
Enter fullscreen mode Exit fullscreen mode

In this example, the flag variable is declared as volatile, ensuring that changes made by one thread are immediately visible to the other thread.

Example 2: Double-Checked Locking Idiom:

public class Singleton {
    private static volatile Singleton instance;

    private Singleton() {
        // Private constructor to prevent instantiation
    }

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (Singleton.class) {
                if (instance == null) {
                    instance = new Singleton();
                }
            }
        }
        return instance;
    }
}
Enter fullscreen mode Exit fullscreen mode

The volatile keyword in the Singleton example ensures that changes made during the creation of the singleton instance are visible to all threads, providing efficient synchronization. In Java, a function or an instance of code can be marked as synchronized by using a synchronized block. Thread safety is ensured for crucial code sections by limiting the number of threads that can access a synchronized block at once.

Conclusion:

By understanding its characteristics and using it judiciously, developers can write thread-safe code, avoiding pitfalls related to visibility and consistency. Although volatile is a useful tool, more complicated circumstances and compound activities require the consideration of other synchronization techniques. When Java developers become proficient with volatile, they may design dependable and effective concurrent programs.

Sample Real World Example :

https://github.com/tharindu1998/java-volatile-example/tree/main

Top comments (0)