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?

Was it helpful?

Solution

compareAndset(false, true) will return false if the value is already true.
It's actually equivalent to !getAndSet(true).

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top