Volatile boolean vs AtomicBoolean

118,736

Solution 1

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.

Solution 2

I use volatile fields when said field is ONLY UPDATED by its owner thread and the value is only read by other threads, you can think of it as a publish/subscribe scenario where there are many observers but only one publisher. However if those observers must perform some logic based on the value of the field and then push back a new value then I go with Atomic* vars or locks or synchronized blocks, whatever suits me best. In many concurrent scenarios it boils down to get the value, compare it with another one and update if necessary, hence the compareAndSet and getAndSet methods present in the Atomic* classes.

Check the JavaDocs of the java.util.concurrent.atomic package for a list of Atomic classes and an excellent explanation of how they work (just learned that they are lock-free, so they have an advantage over locks or synchronized blocks)

Solution 3

You can't do compareAndSet, getAndSet as atomic operation with volatile boolean (unless of course you synchronize it).

Solution 4

AtomicBoolean has methods that perform their compound operations atomically and without having to use a synchronized block. On the other hand, volatile boolean can only perform compound operations if done so within a synchronized block.

The memory effects of reading/writing to volatile boolean are identical to the get and set methods of AtomicBoolean respectively.

For example the compareAndSet method will atomically perform the following (without a synchronized block):

if (value == expectedValue) {
    value = newValue;
    return true;
} else {
    return false;
}

Hence, the compareAndSet method will let you write code that is guaranteed to execute only once, even when called from multiple threads. For example:

final AtomicBoolean isJobDone = new AtomicBoolean(false);

...

if (isJobDone.compareAndSet(false, true)) {
    listener.notifyJobDone();
}

Is guaranteed to only notify the listener once (assuming no other thread sets the AtomicBoolean back to false again after it being set to true).

Solution 5

volatile keyword guarantees happens-before relationship among threads sharing that variable. It doesn't guarantee you that 2 or more threads won't interrupt each other while accessing that boolean variable.

Share:
118,736

Related videos on Youtube

JeffV
Author by

JeffV

Electronics Technologist, currently working as a Software Engineer on VR Simulation Systems. Primarily work in Modern C++, C (embedded), Java, C#. Involved in full engineering life cycle including requirements analysis, system decomposition, high level and low level design, implementation and system verification. Designed and implemented sonar processing systems for beam forming line arrays using distributed services and message passing with ZeroMQ. Designed and implemented VR training simulators with hardware stimulation. Designed and implemented wireless blasting receivers for through the earth communications. Extreme low power and reliability design goals: 6mos on a single C-cell battery. Spend my spare time with my wife and daughter, and enjoy mountain biking, boating, scuba, photography and flying. I like to ask the good questions so all can benefit from the answers. Hard to beat the fastest guns in the west around here. ;-)

Updated on October 23, 2020

Comments

  • JeffV
    JeffV over 3 years

    What does AtomicBoolean do that a volatile boolean cannot achieve?

    • JeffV
      JeffV over 13 years
      I was looking for a more nuanced answer to: "what are the limitations of each?". For instance, if is is a flag set by one thread and read by one or more others, there is no need for AtomicBoolean. However, as I am seeing with these answers, if thread are sharing a variable in a multiple threads can write and are acting on the result of their reads, AtomicBoolean brings CAS type non-locking operations into play. I'm learning quite a bit here, actually. Hopefully, others will benefit too.
    • Flow
      Flow about 10 years
      possible duplicate of volatile boolean vs. AtomicBoolean
    • sactiw
      sactiw over 6 years
      volatile boolean will need explicit synchronization to handle race conditions, in other words, scenario like shared resource being updated (change of state) by multiple threads e.g. increment/decrement counter or flipping boolean.
    • Vadzim
      Vadzim over 4 years
  • Jason S
    Jason S over 13 years
    -1: you're giving examples but not really explaining the difference between a volatile and an Atomicxxxx.
  • Cephalopod
    Cephalopod over 13 years
    Please have a look at the original question. "Allow atomic modifications" is a valid answer.
  • Maciej Biłas
    Maciej Biłas about 13 years
    Boolean (as in primitive type) access is atomic in Java. Both reads and assignments. So no other thread will "interrupt" boolean operations.
  • dolmen
    dolmen over 11 years
    The question is not about volatile. The question is about volatile boolean vs AtomicBoolean.
  • John Haager
    John Haager over 11 years
    -1: the question specifically asked about boolean, which is a unique case compared to the other data types and should be explained directly.
  • Cephalopod
    Cephalopod about 11 years
    sgp15, volatile accesses are synchronizing actions (docs.oracle.com/javase/specs/jls/se7/html/…), as such, they define an order for concurrent events which makes them equivalent to locking on the same monitor.
  • Man of One Way
    Man of One Way over 10 years
    @sgp15 It has to do with synchronization as of Java 5.
  • Xairoo
    Xairoo about 10 years
    So in the volatile boolean example, how would using an AtomicBoolean be any different? This would be the actual question being asked, and other than the getAndSet() method (assuming you actually needed that ability), I am not sure there is any difference.
  • Cephalopod
    Cephalopod about 10 years
    @Robin, you can always replace a volatile with an Atomic*. But sometimes, it isn't necessary and you can safe some overhead. Replacing Atomics with volatile will hurt.
  • Xairoo
    Xairoo about 10 years
    How will it hurt? Specifically for AtomicBoolean, not Atomics in general. I would rather code to a boolean directly, as the code is much more readable than using the get/set methods of an AtomicBoolean.
  • Xairoo
    Xairoo about 10 years
    This is true, but wouldn't this be a pretty rare requirement for a boolean?
  • Cephalopod
    Cephalopod about 10 years
    flag = !flag on a volatile boolean is not thread-safe. If you are using only get and set of the atomic variable, switching should be possible though.
  • znlyj
    znlyj almost 8 years
    @ksl I think @teto want to describe that if only one thread modify the boolean var, we should choose volatile boolean.
  • Ravindra babu
    Ravindra babu almost 8 years
    Excellent summary.
  • Gray
    Gray over 7 years
    I'm sorry but how does this answer the question? An Atomic* class wraps a volatile field.
  • StvnBrkdll
    StvnBrkdll over 7 years
    If the boolean value is read by many threads, but written by only one thread, then volatile boolean is sufficient. If there are also many writers, you may need AtomicBoolean.
  • Ustaman Sangat
    Ustaman Sangat over 7 years
    @Robin think about using it to control a lazy invocation of a initialization method.
  • rents
    rents about 7 years
    The correct answer should be that it provides you a compare and set function which isn't possible with volatile boolean (without explicitly synchronizing). This answer isn't very clear. Simpler is better. I would ask OP to consider editing the answer since this is the accepted answer.
  • bvdb
    bvdb almost 7 years
    This answer is just wrong in my opinion. AtomicBoolean is just a wrapper for a primitive boolean, see other answers. i.e. you want to use an object (e.g. Boolean) but you still want to mark it volatile --> use AtomicBoolean
  • Max Barraclough
    Max Barraclough about 6 years
    "They are just totally different." No, they are very similar. The docs state explicitly that compareAndSet is the whole point: docs.oracle.com/javase/7/docs/api/java/util/concurrent/atomi‌​c/…
  • Arefe
    Arefe over 5 years
    Short, crispy and to the point. volatile only works in the cases where the owner thread has the ability to update the field value and the other threads can only read.
  • jocull
    jocull about 5 years
    Aren't CPU caches the main factor for setting volatile? To ensure that the value read is actually what it was set to most recently
  • fool4jesus
    fool4jesus almost 4 years
    Actually I would think this is one of the main use cases.
  • minsk
    minsk almost 4 years
    -1 because first, the questions is specifically about boolean (not integer increments). Second, Java reference reads/writes are atomic and volatile adds read guarantee.. so this answer with "They are just totally different" -- looks to me like the answerer doesn't understand the question
  • minsk
    minsk almost 4 years
    "If you have only one thread modifying your boolean, you can use a volatile boolean. " Then If you use one thread, why would u need volatile (?).. You should remove first paragraph to make the answer better ..
  • Cephalopod
    Cephalopod almost 4 years
    @minsk Yeah, I totally missed the question. That's why my answer immediately got accepted.
  • Falkreon
    Falkreon almost 4 years
    @ChakladerAsfakArefe Nope! As MoveFast says, the only thing you can't do is read+modify+write. So, for example, with some volatile boolean keepRunning = true; in a worker thread, two unrelated threads could call a cancel method on the worker that sets keepRunning = false;, and the worker thread will correctly pick up on the latest value written. The only thing that won't work is on the order of keepRunning = !keepRunning; because that's a read-modify-write.
  • Falkreon
    Falkreon almost 4 years
    To clarify: You could even have an "un-cancel" method that sets keepRunning = true;. "Nothing is true, everything is permitted" :)
  • Falkreon
    Falkreon almost 4 years
    @minsk one thread writing, one or more threads reading. You won't run into threading problems if you follow that pattern, but it's not quite correct either; see my comments on MoveFast's answer.
  • cmhteixeira
    cmhteixeira over 3 years
    @Falkreon You can certainly run into problems even with that pattern. Namely visibility problems, on which 1 or more reading threads will not "see" the updated result written by the writer thread. that is in fact the problem that volatile solves.
  • Falkreon
    Falkreon over 3 years
    @CarlosTeixeira that's exactly what I mean. volatile boolean can be safely written to, just not negated; negation is a read-modify-write cycle. But just myVolatileBool = false; is threadsafe - because that's what volatile does, forces any writes to go to the same heap memory, and forces any reads to come from heap memory.
  • Nam San
    Nam San over 2 years
    @android developer My answer doesn't mention anything about performance! Can you clarify which part of the answer made you think that? Typically volatile variables are implemented with memory fencing instructions if they exist on the CPU and not with synchronisation/locks. This is similar to how AtomicXXX classes use compare-and-set or load-linked store-conditional instructions if they exist on the CPU.
  • android developer
    android developer over 2 years
    Sorry removed. I think I wrote it to the wrong place. Anyway, which one (volatile vs Atomic) is better in terms of performance, if all you use them for is get&set (without CAS)?
  • Nam San
    Nam San over 2 years
    @android developer If you check the source code, you'll see that the AtomicBoolean get() method is implemented by reading a volatile int field and comparing it to 0 while the set() method is implemented by writing a 0 or 1 to the volatile int field. So the performance of the actual read or write will be very similar if not identical between AtomicBooleans and volatile booleans. The AtomicBoolean will have the overhead of the extra function call and comparison if the JIT was unable to optimise them away. If you have many then a volatile boolean will be more efficient in terms of memory and GC.
  • android developer
    android developer over 2 years
    So it's a tiny bit better to use volatile instead, if that's the scenario. OK thanks.