307

How I can use AtomicBoolean and what is that class for?

ADEpt
  • 5,504
  • 1
  • 25
  • 32
yart
  • 7,515
  • 12
  • 37
  • 37

5 Answers5

314

When multiple threads need to check and change the boolean. For example:

if (!initialized) {
   initialize();
   initialized = true;
}

This is not thread-safe. You can fix it by using AtomicBoolean:

if (atomicInitialized.compareAndSet(false, true)) {
    initialize();
}
Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
  • 71
    It doesn't look like a real-world example - other thread can see `true` when `initialize()` haven't been completed. So, it works only if other threads don't care about completion of `initialize()`. – axtavt Dec 21 '10 at 16:19
  • 11
    @axtavt: I think it's a perfectly valid real-world example if `initialized` is simply being used to ensure that one and only one thread will invoke the `initialize()` method. Obviously `initialized` being true doesn't mean that initialization has definitely completed in this case, so _maybe_ a slightly different term would be better here. Again, it depends on what it's being used for. – ColinD Dec 21 '10 at 16:24
  • 23
    you would need 2 booleans for initStarted and initCompleted, then the first thread sets initStarted and calls initialise(), the rest wait until initCompleted is true. – Martin Dec 21 '10 at 17:32
  • with this solution (and also if you use 2 booleans) you cannot avoid for many threads to start the initialisation in parallel. If this is a problem (for example because it involve DB access) than using a Future is a better idea. – Uberto Feb 07 '13 at 09:35
  • Care to change the `initialize()` method to be `start()` or something else that doesn't get into the problem around the class being used by threads before it is fully initialized? Thanks. – Gray Oct 04 '13 at 17:23
  • 4
    @Bozho - reads and writes to *boolean* fields are atomic right?, Now, *volatile* gives me the latest value of the boolean field. So, effectively, wouldn't `volatile boolean` be same as `AtomicBoolean`?. – TheLostMind Jul 30 '14 at 14:29
  • 4
    @TheLostMind I'm pretty late to the party, but what you would miss are functionalities like `compareAndSet`, which are effectively not implementable without some kind of synchronization – gcali Sep 01 '15 at 14:58
  • 1
    This is a bad example. Presumably a function is checking for initialization because the class needs some initialization. In this case, the initialization flag could be set to true, initialization not complete, and another thread comes by and see the initialize flag is set to true and continues without initialization having happened! – lmat - Reinstate Monica Jul 06 '16 at 14:06
  • 3
    @Martin: There's no direct way to wait for a boolean to become true; you need additional mechanisms. The most sensible approach is to use a `synchronized` block, in which case you no longer need an `AtomicBoolean`, just a `volatile boolean`. (`if(! this.initialized) { synchronized(this) { if(! this.initialized) { initialize(); this.initialized = true; } } }` will ensure that only one thread calls `initialize`, and that all other threads wait for it to have done so, provided that `initialized` is marked `volatile`.) – ruakh Oct 14 '16 at 23:51
  • it's not only about threading, but just that you can reference to this `AtomicBoolean` instance from different classes and get the same value, if you send `Boolean` instance to another class constructor then you get new variable, but with `AtomicBoolean` you get the same instance and reference with the same value and value is changed across all instances (would be same, it doesn't matter where from which instance it was changed) – user924 Apr 22 '18 at 14:11
69

Here is the notes (from Brian Goetz book) I made, that might be of help to you

AtomicXXX classes

  • provide Non-blocking Compare-And-Swap implementation

  • Takes advantage of the support provide by hardware (the CMPXCHG instruction on Intel) When lots of threads are running through your code that uses these atomic concurrency API, they will scale much better than code which uses Object level monitors/synchronization. Since, Java's synchronization mechanisms makes code wait, when there are lots of threads running through your critical sections, a substantial amount of CPU time is spent in managing the synchronization mechanism itself (waiting, notifying, etc). Since the new API uses hardware level constructs (atomic variables) and wait and lock free algorithms to implement thread-safety, a lot more of CPU time is spent "doing stuff" rather than in managing synchronization.

  • not only offer better throughput, but they also provide greater resistance to liveness problems such as deadlock and priority inversion.

soshial
  • 5,906
  • 6
  • 32
  • 40
Aravind Yarram
  • 78,777
  • 46
  • 231
  • 327
46

There are two main reasons why you can use an atomic boolean. First it's mutable, you can pass it in as a reference and change the value that is associated to the boolean itself, for example.

public final class MyThreadSafeClass{

    private AtomicBoolean myBoolean = new AtomicBoolean(false);
    private SomeThreadSafeObject someObject = new SomeThreadSafeObject();

    public boolean doSomething(){
         someObject.doSomeWork(myBoolean);
         return myBoolean.get(); //will return true
    }
}

and in the someObject class

public final class SomeThreadSafeObject{
    public void doSomeWork(AtomicBoolean b){
        b.set(true);
    }
}

More importantly though, it's thread safe and can indicate to developers maintaining the class, that this variable is expected to be modified and read from multiple threads. If you do not use an AtomicBoolean, you must synchronize the boolean variable you are using by declaring it volatile or synchronizing around the read and write of the field.

Pang
  • 9,564
  • 146
  • 81
  • 122
John Vint
  • 39,695
  • 7
  • 78
  • 108
  • 5
    For the love of god, that was only to show the mutability of the object itself. I specifically wrote that for demonstration purposes. – John Vint Dec 21 '10 at 16:24
  • And further more, if that was ALL that was happening then yes, it will always return true – John Vint Dec 21 '10 at 16:25
  • That isn't proving if it is or isnt thread-safe. I can finish my snippets of code to make the class very thread-safe, but that only kills my point. – John Vint Dec 21 '10 at 17:23
  • There you go, a thread-safe class that in no way helps what I was explaining – John Vint Dec 21 '10 at 17:26
  • 2
    I think that only Volatile is not enough. Think about a situation in which two threads that read and write the same value directly from the main memory, there isn't any sync between those threads - hance concurrency problems might arise. – Shay Tsadok Mar 24 '15 at 20:31
  • @ShayTsadok Can you explain your point further? I am having trouble associating it to may answer. If someone were to use an `AtomicBoolean` with say, compareAndSet, then there wouldn't be any race conditions. – John Vint Mar 24 '15 at 21:36
  • 1
    You wrote in the answer "If you do not use an AtomicBoolean you must synchronize the boolean variable you are using by **declaring it volatile** or synchronizing around the read and write of the field", I think that volatile won't be enough. – Shay Tsadok Mar 24 '15 at 21:39
  • 1
    You're right it wouldn't be enough for atomic set then check operations, though there wasn't enough context from the OP to make that assumption. To say, volatile might not be enough is always true depending on the situation of course. – John Vint Mar 24 '15 at 21:54
23

The AtomicBoolean class gives you a boolean value that you can update atomically. Use it when you have multiple threads accessing a boolean variable.

The java.util.concurrent.atomic package overview gives you a good high-level description of what the classes in this package do and when to use them. I'd also recommend the book Java Concurrency in Practice by Brian Goetz.

Cameron Skinner
  • 51,692
  • 2
  • 65
  • 86
6

Excerpt from the package description

Package java.util.concurrent.atomic description: A small toolkit of classes that support lock-free thread-safe programming on single variables.[...]

The specifications of these methods enable implementations to employ efficient machine-level atomic instructions that are available on contemporary processors.[...]

Instances of classes AtomicBoolean, AtomicInteger, AtomicLong, and AtomicReference each provide access and updates to a single variable of the corresponding type.[...]

The memory effects for accesses and updates of atomics generally follow the rules for volatiles:

  • get has the memory effects of reading a volatile variable.
  • set has the memory effects of writing (assigning) a volatile variable.
  • weakCompareAndSet atomically reads and conditionally writes a variable, is ordered with respect to other memory operations on that variable, but otherwise acts as an ordinary non-volatile memory operation.
  • compareAndSet and all other read-and-update operations such as getAndIncrement have the memory effects of both reading and writing volatile variables.
OscarRyz
  • 196,001
  • 113
  • 385
  • 569