Search code examples
javaconcurrencybooleanvolatileatomicboolean

Volatile boolean vs AtomicBoolean


What does AtomicBoolean do that a volatile boolean cannot achieve?


Solution

  • They are just totally different. Consider this example of a volatile integer:

    volatile int i = 0;
    void incIBy5() {
        i += 5;
    }
    

    If two threads call the function concurrently, i might be 5 afterwards, since the compiled code will be somewhat similar to this (except you cannot synchronize on int):

    void incIBy5() {
        int temp;
        synchronized(i) { temp = i }
        synchronized(i) { i = temp + 5 }
    }
    

    If a variable is volatile, every atomic access to it is synchronized, but it is not always obvious what actually qualifies as an atomic access. With an Atomic* object, it is guaranteed that every method is "atomic".

    Thus, if you use an AtomicInteger and getAndAdd(int delta), you can be sure that the result will be 10. In the same way, if two threads both negate a boolean variable concurrently, with an AtomicBoolean you can be sure it has the original value afterwards, with a volatile boolean, you can't.

    So whenever you have more than one thread modifying a field, you need to make it atomic or use explicit synchronization.

    The purpose of volatile is a different one. Consider this example

    volatile boolean stop = false;
    void loop() {
        while (!stop) { ... }
    }
    void stop() { stop = true; }
    

    If you have a thread running loop() and another thread calling stop(), you might run into an infinite loop if you omit volatile, since the first thread might cache the value of stop. Here, the volatile serves as a hint to the compiler to be a bit more careful with optimizations.