compareAndset(false, true)
will return false
if the value is already true
.
It's actually equivalent to !getAndSet(true)
.
What is the difference between AtomicBoolean.set(flag) and AtomicBoolean.compareAndSet(!flag, flag)?
-
29-11-2021 - |
Question
I wonder if there is any difference(or possible side effects) between calling:
AtomicBoolean.set(true)
and
AtomicBoolean.compareAndset(false, true)
The JavaDoc of AtomicBoolean#set
states:
Unconditionally sets to the given value.
While AtomicBoolean#compareAndSet
states:
Atomically sets the value to the given updated value if the current value == the expected value.
In both cases the value will be set to true. So what is the difference?
Solution
OTHER TIPS
Well the text that you quoted says explicitly what the difference between the two operations is. But to make it clearer, if you ignore the atomicity aspect, the first one is equivalent to:
public void set(boolean newValue) {
this.value = newValue;
}
and the second one is equivalent to:
public boolean compareAndSet(boolean expected, boolean newValue) {
if (this.value == expected) {
this.value = newValue;
return true;
} else {
return false;
}
}
For your example, set(true)
sets the state to true
, and compareAndset(false, true)
sets the state to true
iff it is not already true
. So, yes, the net effect on the state of the AtomicBoolean
is the same.
However, you will notice that the return
value differs depending on the initial state of the AtomicBoolean
object ... so from that perspective the methods are not equivalent, even with those argument values.
Landed here looking for the answer from performance perspective. Being unsure about the native implementation v decision blocks, I ended up writing code to evaluate the same. Per results, set() definitely is on the upper hand of performance as it does not go through multiple decision blocks. Please find the code and output below.
public static void main(String[] args) {
boolean curValue = true;
boolean dummyValue = true;
int attempts = Integer.MAX_VALUE;
AtomicBoolean test = new AtomicBoolean(curValue);
long start = System.currentTimeMillis();
for(int i=0; i<attempts; i++){
test.set(true);
dummyValue = !dummyValue;
}
System.out.println("time taken for set: "+(System.currentTimeMillis()-start));
start = System.currentTimeMillis();
for(int i=0; i<attempts; i++){
test.compareAndSet(curValue, curValue); // always set the same value
dummyValue = !dummyValue;
}
System.out.println("time taken for compareAndSet - same value case: "+(System.currentTimeMillis()-start));
curValue = !curValue;
start = System.currentTimeMillis();
for(int i=0; i<attempts; i++){
test.compareAndSet(curValue, !curValue); // always invert
curValue = !curValue;
}
System.out.println("time taken for compareAndSet - inversion case: "+(System.currentTimeMillis()-start));
}
Output:
time taken for set: 2689
time taken for compareAndSet - same value case: 15559
time taken for compareAndSet - inversion case: 14802
The difference between set() and compareAndSet() methods of AtomicBoolean can be found in thread locking mechanism.
Thread safty can be achieved with the following code.
public class AtomicBooleanSample {
private AtomicBoolean locked = new AtomicBoolean(false);
private void lock() {
while(!this.locked.compareAndSet(false, true)) {
//a thread will be locked here
}
}
private void unlock() {
this.locked.set(false);
}
}
For a shared resource, when the first thread executes a lock()
method, the value of locked
instance variable will be set to true
as the expected value is same as the value of locked
and it acquires the lock to access a shared resource.
Before first thread calls unlock()
method, if another thread tries to lock, it will be failed since the value of locked
is different (true
that does not meet the expected value false
) and it runs in the loop until the first thread sets the value of locked
to false.
The CAS algorithm will have a performance implication in high contention situations since compareAndSet(false, true)
is retired until it succeeds. So if atomicity is not required plain boolean value might be a better option.