Reputation: 1479
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()
?
Upvotes: 4
Views: 986
Reputation: 306
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:
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.
Upvotes: 1
Reputation: 6038
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
Upvotes: 4
Reputation: 328785
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));
Upvotes: 3
Reputation: 44476
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());
}
Upvotes: 1