When is it preferable to use volatile boolean in Java rather than AtomicBoolean?

25,059

Solution 1

Essentially all AtomicBoolean is a volatile boolean in an object.

There will be a small overhead per object. Probably insignificant, but possibly more memory to get into cache.

If you need to use AtomicBooleanFieldUpdater then there is quite a lot of performance overhead.It can be okay if you aren't going to do it often (as attach in NIO).

Solution 2

The main difference between AtomicBoolean and volatile from a practical point of view is that the compare-and-set operation isn't atomic with volatile variables.

 volatile boolean b;

 void foo() {
   if( b ) {
     //Here another thread might have already changed the value of b to false
     b = false;
   }
 }

But seeing as all your concurrent writes are idempotent and you only read from one thread, this shouldn't be a problem.

Solution 3

I'm not sure I completely agree with the other answers here; biziclop's answer is right as far as it goes, but I'm not sure we can conclude that you're safe unless we know more detail.

In the simple case, interleaving might look like this:

Thread 1 (writer)   Thread 2 (Writer)  Thread 3 (Reader)
-----------------   -----------------  -----------------
flag = true;
                                       if (flag) {
                    flag = true;
                                         flag = false;
                                         doStuff();

and this might be fine (the second set of flag to true doesn't matter, as doStuff() will still presumably see whatever Thread 2 needs doing.

However if you reverse the order thread 3 does:

Thread 1 (writer)   Thread 2 (Writer)  Thread 3 (Reader)
-----------------   -----------------  -----------------
flag = true;
                                       if (flag) {
                                         doStuff();
                    flag = true;
                                         flag = false;

then Thread 2's update could be lost.

Of course you need to be similarly careful with whatever else Thread 2 does, to make sure it's visible to Thread 3. If there's other state that Thread 2 needs to set, order becomes important there too.

In the simple case, yes you're fine, but if it gets more complex than just simple flicking of flags then this becomes much harder to reason about.

Solution 4

There is a lot of good information here. However, I would add another difference that may be useful. You can have an array of AtomicBooleans but you can't (to my knowledge) have an array of volatile booleans.

Solution 5

Then one or more threads set the flag (but not clear it). If I have one thread that reads the flag, and if set, does an action, and then clears the flag, is volatile adequate?

Yes, if you don't need the special abilities of AtomicBoolean, it's perfectly fine to use volatile for this. In fact, this is one of the few reasonable uses for volatile.

Share:
25,059
Jason S
Author by

Jason S

Updated on January 26, 2020

Comments

  • Jason S
    Jason S over 4 years

    I've looked at the other volatile vs. Atomicxxxx questions in SO (including this one) and have read the description of java.util.current.atomic, and I am not quite satisfied with the nuances.

    If I'm trying to decide between using volatile boolean and AtomicBoolean, are there practical differences besides the atomic read-modify-write operations offered by AtomicBoolean? (e.g. compareAndSet() and getAndSet())

    Suppose I have

    volatile boolean flag;
    

    Then one or more threads set the flag (but not clear it). If I have one thread that reads the flag, and if set, does an action, and then clears the flag, is volatile adequate?

    Is there a higher cost to AtomicBoolean than volatile boolean, in terms of

    • memory space
    • performance hit (volatile boolean appears to require memory fencing, AtomicBoolean appears to require memory fencing + some minor locking on CAS operations as per the java.util.current.atomic description)

    My gut call is to just go with AtomicBoolean and be safe, but I want to understand if there's ever a situation to use volatile boolean instead (e.g. if I had thousands of instances of them and performance were an issue).