Java Volatile Tutorial

In this section, we will learn what the volatile is and how it works in Java concurrency.

Variable Visibility Problem

So far, we mention that each thread we create in a program has its own stack and working memory. That means when a thread needs to read or write to a shared variable, it may run the read/write operations on its working memory and at the end when the work of that thread is done, it updates the main memory where the shared variable is located.

This may pose a problem if multiple threads are working on the same variable.

Imagine that two threads request the access to a shared variable. Here, both threads want to update the current value of the variable. Now, if each thread runs this update operation on its own working memory, the other threads won’t be able to know about this update until the work of that thread is done at some point in the future when it flushes the update to the main memory!

Note: depending on the underlying structure of a system, the update of a shared resource on the main memory might happen immediately when a thread changes the value of that variable. But this is not always guaranteed!

Now, to solve the problem and make sure that each read or write to a shared resource is done on the main memory ONLY, Java provided a keyword called `volatile`.

What is Volatile in Java? And What does volatile mean?

In order to make threads to read/ write directly to a variable in the main memory instead of on their cache, Java provided a keyword called `volatile` that could be applied to a resource (an instance variable or a static variable) and it will guarantee that any read/write to that variable by any thread will be done in the main memory only.

This means no threads can cache the value of a volatile variable.

Note:

  • A local variable cannot be turned into volatile! This is because a local variable exists only within the stack of a thread and no threads can access the value of that variable. So there’s no need to set such type of variables into volatile.

How to declare a field as Volatile? (Volatile syntax)

This is how we can create a volatile variable in Java:

Access-specifier volatile data-type variableName;

Example:

public volatile int count;

Example: using volatile field in program

public class Main {
    public volatile double count = 0;
    public static void main(String[] args) {
        Main main = new Main();
        Thread t1 = new Thread(main::inc, "Thread-one");
        Thread t2 = new Thread(main::read, "Thread-two");

        t1.start();
        t2.start();

    }
    private void inc() {
        for (int i = 0 ; i<5; i++){
            count++;
            System.out.println("From the perspective of "+Thread.currentThread().getName()+" the value of count variable is: "+ count);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    private void read(){
        for (int i = 0 ; i <6; i++){
            System.out.println("Thread-two: The value of the count variable is: " + count);
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

Output:

Thread-two: The value of the count variable is: 1.0

From the perspective of Thread-one the value of count variable is: 1.0

From the perspective of Thread-one the value of count variable is: 2.0

Thread-two: The value of the count variable is: 2.0

From the perspective of Thread-one the value of count variable is: 3.0

Thread-two: The value of the count variable is: 3.0

Thread-two: The value of the count variable is: 3.0

From the perspective of Thread-one the value of count variable is: 4.0

From the perspective of Thread-one the value of count variable is: 5.0

Thread-two: The value of the count variable is: 5.0

Thread-two: The value of the count variable is: 5.0

In this example, the thread one is trying to increase the value of the `count` variable, which is a shared resource, and the `thread-two` is trying to read its value.

Now, because the variable is declared as `volatile`, any read and write operation on this variable will be done in the main memory where the variable is stored.

Since any read/write operation on a volatile variable is done in the main memory, we can use such variables as flag as well! For example, a volatile variable of type boolean can become a flag. If that variable’s value was true, then a thread can continue to run, but if another thread turned the value of the variable to false, that means the work of the first thread is done and it should stop immediately.

Example: volatile variables as flags in Java

public class Main {

    public volatile static boolean run = true;

    public static void main(String[] args) {
        Main main = new Main();
        Thread t1 = new Thread(Main::run, "Thread-one");

        t1.start();

        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        main.stop();

    }
    private static void run() {
        System.out.println("Thread is running...");
        while(run){
            try {
                System.out.println("Thread went to sleep");
                Thread.sleep(1000);

            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("Thread stopped...");
    }
    public void stop(){
        Main.run = false;
    }
}

Output:

Thread is running...

Thread went to sleep

Thread went to sleep

Thread went to sleep

Thread stopped...

Leave a Reply