简体   繁体   中英

Can AtomicBoolean replace volatile boolean?

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            
        }
    }

}

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 (aka, 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 封装了一个 volatile 所以它们基本相同,不同之处在于它提供了更高级别的操作,例如用于实现增量的 CompareAndSwap。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM