11

In java, with my knowledge, volatile variable make a thread reads/writes directly to main CPU (not in cache of each thread), so make its change visibles to other threads.

The thing I don't know is : So, why this work (of volatile) can prevent compiler/CPU reorder statement of code.

thanks :)

hqt
  • 29,632
  • 51
  • 171
  • 250
  • Note that this thing about volatile making reads avoid caches is a purely theoretical construct and does not really have all that much to do with what `volatile` actually does on real hardware. We just imagine that there's all kinds of things an implementation might do and that `volatile` guarantees that optimizations don't produce particular behaviors that we need to prohibit in particular cases. – David Schwartz Sep 26 '16 at 10:42

2 Answers2

24

Here is a very good example illustrating the issue the prohibition on reordering is aimed to address (taken from here):

class VolatileExample {
    int x = 0;
    volatile boolean v = false;
    public void writer() {
        x = 42;
        v = true;
    }
    public void reader() {
        if (v == true) {
            //uses x - guaranteed to see 42.
        }
    }
}

In this example, v is volatile, but x is not. If writer and reader are executed concurrently and the reader sees v set to true, x is guaranteed to be 42. Prior to Java-5, compiler was free to re-order the writes to x and v, so you could see x at zero after you've seen v set to true. This was confusing, and lead to subtle errors. Java-5 memory model addressed this issue by making volatile writes almost equivalent to synchronization.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
  • 1
    I don't see how reader is guaranteed see x at 42. Sure the x=42 can happen before v=true, but reader() could still see a cached value of 0, no? – Shawn Feb 08 '12 at 04:13
  • 1
    @Shawn Until Java-5 that was correct, but Java-5 memory model makes sure that all writes complete before the volatile write. See link for details. – Sergey Kalinichenko Feb 08 '12 at 04:16
  • 1
    I just ran my code based on this answer and noticed the following fact. if v is declared true, the compiler can delete the line `v = true;`, and the value of x will remain 0 in `reader()`. See [my gist](https://gist.github.com/anonymous/3e5fc26aa20a85757368) – Maksim Dmitriev Mar 07 '16 at 12:48
  • 1
    but if x is set after v is set in writer(), then reader() either see x to be 42 or 0 – voipp Jun 05 '16 at 17:20
5

That's just how the language is defined. Informally, marking a variable volatile in Java specifically tells the compiler that it should not reorder statements around it or optimize on its value, since that value might be modified concurrently in another thread. The particular implementation of the JVM is then responsible for respecting this volatile modifier and taking appropriate precautions not to incorrectly optimize the program.

If you'd like more specific details about what language-level guarantees there are to ensure that volatile works correctly, you may want to look at the Java Language Specification's description of the Java memory model, which defines the abstract rules governing thread behavior. It also describes how volatile interacts with these rules.

Hope this helps!

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065