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

JavaConcurrencyAtomicVolatile

Java Problem Overview


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).

Java Solutions


Solution 1 - Java

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 2 - Java

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 3 - Java

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 - Java

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 - Java

> 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJason SView Question on Stackoverflow
Solution 1 - JavabiziclopView Answer on Stackoverflow
Solution 2 - JavaTom Hawtin - tacklineView Answer on Stackoverflow
Solution 3 - JavaCowanView Answer on Stackoverflow
Solution 4 - JavasnapfractalpopView Answer on Stackoverflow
Solution 5 - JavaSergei TachenovView Answer on Stackoverflow