Skip to main content
查利博客

Java Concurrency - Volatile Keyword

In this tutorial, we are going to learn the volatile variables in Java with examples. The volatile keyword is a light-weight synchronization mechanism that provides memory visibility and prevents the compiler reordering code. In short, if a variable is declared as volatile, all reads are read from the main memory and return the most updated write by any thread. A Typical usage of volatile variables is to check a flag to determine when to exit a loop. Let's go through some examples.

Shut Down Server #

We pretend there is a server running in background, another thread can shut it down by modifying the shutdown to true.

Without volatile keyword:

public class VolatileExample extends Thread {
  boolean shutdown = false;

  public void run() {
    while (!shutdown) {
    }
  }

  public static void main(String[] args) throws InterruptedException {
    VolatileExample t = new VolatileExample();
    t.start();
    Thread.sleep(2000);
    t.shutdown = true;
    t.join();
  }
}

As expected, this example will run indefinitely because the thread t sees the cached value of the field shutdown even the main thread updates it. To prevent this happens, add the volatile modifier to shutdown variable:

boolean volatile shutdown = false;

Now, your application will terminate after two seconds.

Note: It is likely you want to print something inside the run() method block and hope the application print the message forever, But in fact the application also stops after two seconds.

public void run() {
  while (!shutdown) {
    System.out.println("Server is running!");
  }
}

The reason is that the System.out.println method is synchronized and so the thread t are actually getting updated (synchronized) every time.

Why volatile is needed in double-checked locking? #

In my previous article, I have talked about that the race condition can be avoided by using the Double-Checked Locking. But did you know why the volatile keyword is used? This is because a non-fully initialized object may being used when another thread sees that assignment and the volatile keyword prevent that. See this page for more information about double-checked locking. However, so far I cannot find an example of non-fully initialized object in online so please let me know if you find it!

Happens-Before Guarantee #

Since compiler can reorder our code for optimizing the performance, this may produce some unexpected behavior. Therefore, the Java volatile keyword provides a happens-before guarantee. From this tutorial, we can see that there are two types of happens-before guarantees:

Writes to Example:

  this.a = a;  // this.a is a non volatile variable
  this.b = b;  // this.b is a non volatile variable
  this.c = c;  // this.c is a volatile variable

The only possible write orders are (a, b, c) or (b, a, c). c should be the last.

Reads from Example:

  int a = this.a;  // this.a is a volatile variable
  int b = this.b;  // this.b is a non volatile variable
  int c = this.c;  // this.c is a non volatile variable

The only possible read orders are (a, b, c) or (a, c, b). a should be the first.