58

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

Community
  • 1
  • 1
Jason S
  • 184,598
  • 164
  • 608
  • 970
  • 1
    What are you trying to do with this flag? Are you using the flag to control concurrency, or something else? I'm wondering if the underlying problem would help explain what answer you are looking to find. – Jonathan B Feb 02 '11 at 15:27
  • 1
    `If I have one thread that reads the flag, and if set, does an action, and then clears the flag, is volatile adequate?` Yes, that's exactly what the `volatile` keyword is supposed to solve for you. – Johan Sjöberg Feb 02 '11 at 15:36
  • @Jonathan: it was just one particular example... I was thinking of a program where I have components marked as "dirty" that need persistence. The components mark themselves as "dirty", and a persistence manager finds the dirty components, saves their state, and marks them as non-dirty. – Jason S Feb 02 '11 at 15:43
  • @BuZZ-dEE, that question predates mine but I already read it at the time of writing (could you please read the questions in their entirety, before trying to use modpowers?) and had some much more detailed issues I brought up. So yes, there's overlap, but no, it's not a duplicate. – Jason S Jan 25 '16 at 20:34
  • Related [When I need to use AtomicBoolean in Java](https://stackoverflow.com/questions/4501223/when-i-need-to-use-atomicboolean-in-java) – BuZZ-dEE Jan 25 '16 at 22:00

5 Answers5

75

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.

biziclop
  • 48,926
  • 12
  • 77
  • 104
  • 9
    +1 for bringing up the idempotent concept – Jason S Feb 02 '11 at 15:47
  • There isn't a compare-and-set operation in the language for `volatile`s, so it can't be unatomic. The library supplied compare-and-set operations (`AtomicBooleanFieldUpdate` and friends) are atomic. – Tom Hawtin - tackline Feb 02 '11 at 15:53
  • 2
    @Tom Hawtin - tackline Compare-and-set(or swap) is nevertheless an operation in general, even though there is no built-in implementation of it in java except for the `Atomic*` classes. http://en.wikipedia.org/wiki/Compare-and-set – biziclop Feb 02 '11 at 16:04
  • +1 for focusing on **one** main difference which helped me get started... Also, there is an educating discussion [here](http://www.coderanch.com/t/233792/threads/java/Volatile-boolean-versus-AtomicBoolean). – uTubeFan Mar 29 '12 at 15:40
  • 2
    In your example whatever happens, the result is false. A better example would be `b = !b`. With two threads flipping `b` it should stay the same, but without atomicity, it can fail. – maaartinus Sep 17 '14 at 13:43
  • 1
    @maaartinus What I actually tried to demonstrate was that in the specific case OP described it doesn't matter because the operations are idempotent. But as you say, `b=!b` isn't idempotent and therefore it'll fail. – biziclop Sep 17 '14 at 14:49
  • how about: if ( !bool && (bool = true) ) .. do somethig .. is that atomic ? should be, right ? – mjs Aug 17 '17 at 10:09
  • @momomo No, it isn't. Nor should it be atomic really. – biziclop Aug 17 '17 at 10:42
  • @biziclop how sure are you? – mjs Aug 17 '17 at 18:58
  • @momomo It's difficult to construct an example that would prove it but it would contradict the JLS rules on expression evaluation. [Here's](https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.7.1) the specific example of just this kind of expression. – biziclop Aug 17 '17 at 23:08
20

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

KNU
  • 2,560
  • 5
  • 26
  • 39
Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
19

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.

Cowan
  • 37,227
  • 11
  • 66
  • 65
  • 7
    Good point. Although it is worth mentioning that in the second case AtomicBoolean won't help either. Full-fledged synchronization is needed then. – Sergei Tachenov Feb 03 '11 at 07:12
  • 4
    @Cowen: I've never seen interleaving visualized as such, but it is very clear. I do it mentally when reading threaded code, but this is a good technique to document cases when explaining race conditions/weaknesses in threaded code. – kevinarpe Sep 06 '14 at 10:25
  • @SergeyTachenov Won't AtomicBoolean.getAndSet() in the Thread 3 solve this issue? – Андрей Беньковский Sep 27 '16 at 17:28
  • 1
    @Андрей, I guess it could, but we need more details about what all three threads are doing in order to answer that precisely. It could help thread 3 detect that thread 2 set the flag again, but can't help figure out when that happened and whether the stuff was done with thread 2's update or not. – Sergei Tachenov Sep 27 '16 at 18:18
8

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.

snapfractalpop
  • 2,086
  • 2
  • 21
  • 28
  • 1
    Nope, but you can still have a SynchronizedSet, or other synchronized set of booleans, which safely publish the array – pkran Mar 30 '15 at 12:21
2

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.

Sergei Tachenov
  • 24,345
  • 8
  • 57
  • 73