Home  Synchronization and concurrency  ConcurrentHashMap  Atomic variables

The volatile keyword in Java

It's probably fair to say that on the whole, the volatile keyword in Java is poorly documented, poorly understood, and rarely used. To make matters worse, its formal definition actually changed as of Java 5. Declaring a variable as volatile means:

We say "acts as though" in the second point, because to the programmer at least (and probably in most JVM implementations) there is no actual lock object involved. Unlike synchronized blocks:

As of Java 5, volatile variables have an additional property: thread-local copies of variables are also synchronized with main memory when the variable is accessed, as would be the case when entering and leaving a synchronized block. In other words, they pretty much do have the semantics of a synchronized block, although the lack of an actual lock object means they're generally a more "lightweight" operation. Some authors have described volatile as a "means of avoiding synchronization"1. But if you include memory synchronization, then as of Java 5 this definition isn't quite true.

The volatile property is most often used to implement a "stop request" flag allowing one thread to signal to another to finish:

public class StoppableTask extends Thread {
  private volatile boolean pleaseStop;

  public void run() {
    while (!pleaseStop) {
      // do some stuff...
    }
  }

  public void tellMeToStop() {
    pleaseStop = true;
  }
}

If the variable were not declared volatile (and without other synchronization), then it would be legal for the thread running the loop to cache the value of the variable at the start of the loop and never read it again. If you don't like infinite loops, this is undesirable.

A danger of volatile variables is that they can misleadingly make a non-atomic operation look atomic. For example:

volatile int i;
...
i += 5;

Although it may look it, the operation i += 5 is not atomic. It is more the equivalent to:

// Note that we can't literally synchronize on an int primitive!
int temp;
synchronized (i) {
  temp = i;
}
temp += 5;
synchronized (i) {
  i = temp;
}

So another thread could sneak in the middle of the overall operation of i += 5.

When should I use the volatile keyword?

The glib answer is generally "very rarely". The boolean flag for telling a thread to stop, as exemplified above, is probably the most typical use. In general, volatile variables may be useful where:

On the next page, we continue our discussion by looking at relying on the synchronization in the class loader.

Notes:
1. Cf the description in Chapter 5 of Oaks, S. & Wong, H. (2004), Java Threads, 3rd ed.


Written by Neil Coffey. Copyright © Javamex UK 2008. All rights reserved.