4

1.

volatile boolean bool = false;
// ...
bool = !bool;

2.

volatile AtomicBoolean bool= new AtomicBoolean(false);
// ...
bool.set(!bool.get());

If there are multiple threads running, and one of them needs to swap the value of bool and making the new value visible for other threads, do these 2 approaches have the same problem of allowing for another thread's operation to happen in-between the read and write, or does AtomicBoolean assure that nothing will happen in-between the call to .get() and .set()?

Tirafesi
  • 1,297
  • 2
  • 18
  • 36
  • 1
    there is a `compareAndSet` method in `AtomicBoolean` which should do exactly what you need, but even using that one you need to call `.get()` first, so you need to synchronize anyway. Why there is no out-of-the-box swap/switch or smth. like that, if `AtomicBoolean` , as I see it, was created mainly for this purpose ?) Can't get it :) – ikos23 Feb 14 '18 at 15:58

4 Answers4

4

AtomicBoolean cannot assure nothing will happen between the get() and set().
You could create 3 methods get(), set() and swap() that synchronize on the same object.

You could try something like this:

public class SyncBoolean
{
  public SyncBoolean()
  {
    value = false;
  }

  public synchronized boolean get()
  {
    return (value);
  }

  public synchronized void set(boolean newValue)
  {
    value = newValue;
  }

  public synchronized void swap()
  {
    value = !value;
  }

  private boolean value;

} // class SyncBoolean
Robert Kock
  • 5,795
  • 1
  • 12
  • 20
3

Both versions could fail for the reason you have given. One option would be:

boolean b;
do {
  b = bool.get();
} while (! bool.compareAndSet(b, !b));
assylias
  • 321,522
  • 82
  • 660
  • 783
1

Neither bool = !bool nor bool.set(!bool.get()) are atomic. Wrapping the operation to the synchronized block helps because two threads can't enter it on the same object twice.

synchronized(this) {
    bool.set(!bool.get());
}
Nikolas Charalambidis
  • 40,893
  • 16
  • 117
  • 183
  • 1
    That works (assuming all accesses to bool are synchronised) but kind of defeats the purpose of volatile/AtomicXxx which is to be lock-free. – assylias Feb 14 '18 at 15:36
1

As it has been already mentioned, you can not simply swap value using neither volatile boolean nor AtomicBoolean in one line.

There are two ways you can do it, which also showed above:

  • using one "global" lock/synchronization
  • via while loop and AtomicBoolean.compareAndSet

Whereas the first solution looks easier and just works, in my opinion, in most cases it would be considered as a bad practise and should be avoided. Unless you have a really high count of simultanious modifications of this field by multiple threads, the second solution should outperform the first one.

Nevertheless, if you really favor simplicity and do not need a better performance knowing the cost of this decision, choose the first.

To add my contribution, I have noticed that you defined your atomic variable as volatile, and, just in case, warn you, that if you do not reassign this field and it can be made final, better do it final. volatile applies only to the actual field value and if you do not change it (which you do not using set/compareAndSet methods of AtomicBoolean) and you have made sure, that other threads will see the initialized value (final does it) there is no much sense to use it.

OutOfNPE
  • 286
  • 3
  • 5