Can AtomicBoolean replace volatile boolean?

Viewed 157

Given following code, in which I check a boolean value isInitialised before running some code. if instead of
private static volatile boolean isInitialised;, I use
private static final AtomicBoolean isInitialised = new AtomicBoolean(false);,
it should achieve the same outcome and even the performance difference is negligible?

public class DclSingleton {

    private static volatile boolean isInitialised;
    //private static final AtomicBoolean isInitialised = new AtomicBoolean(false);

    public static void doInit() {
        if (!isInitialised) {
            synchronized (DclSingleton.class) {
                if (!isInitialised) {
                    // do init
                    
                    isInitialised = true;
                }
            }
        }
    }

}

And if I do use AtomicBoolean, would following code achieve the same?

public class DclSingleton {

    // private static volatile boolean isInitialised;
    private static final AtomicBoolean isInitialised = new AtomicBoolean(false);

    public static void doInit() {
        if (isInitialised.compareAndSet(false, true)) {
            // do init            
        }
    }

}
3 Answers

There are two important differences between your two examples.

First, the obvious: The doInit() method in your first example only sets isInitialized=true after initializing the singleton. But, in your second example, it sets the AtomicBoolean instance to true before it initializes the singleton. That could be a problem if a second thread obtains a reference to the singleton after the flag has been set, but before the initialization has completed.

The second problem is less obvious: There is no synchronization after the flag is set in your second example. Nothing establishes a happens before relationship between the initialization code and anything that happens in some other thread. In your first example, the initialization happens before isInitialized=true, and isInitialized=true happens before any other thread tests if(!isInitialized)...

In your second example, if two threads concurrently call doInit(), The Atomic operation ensures that only one of them can enter the initialization code. But even if the winner, by pure chance, actually completes the initialization code before* the other thread starts to use the singleton object, there still is no formal happens before relationship between the first thread doing the initialization and the second thread accessing the singleton.


* "before" in real time (a.k.a., wall clock time). If some event A actually happens before event B in real time, but there is no formal happens before relationship between the two events, then it is possible for some other thread to see the effects of those two events as if they happened in a different order.

Yes it can. The visibility is guarantee.

AtomicBoolean is similar to synchronized but it's considered to outperformed than synchronize due to compareAndSwap utility of CPU cache.

The small difference is it's not make sure the order of execution between multiple threads while synchronized can.

AtomicXxxx wraps a volatile so they are basically same, the difference is that it provides higher level operations such as CompareAndSwap which is used to implement increment.

Related