[英]Can AtomicBoolean replace volatile boolean?
给定以下代码,其中我在运行一些代码之前检查了一个布尔值isInitialised
。 如果不是private static volatile boolean isInitialised;
, 我用private static final AtomicBoolean isInitialised = new AtomicBoolean(false);
,
它应该达到相同的结果甚至性能差异可以忽略不计?
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;
}
}
}
}
}
如果我确实使用AtomicBoolean
,下面的代码会达到同样的效果吗?
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
}
}
}
您的两个示例之间有两个重要区别。
首先,显而易见:第一个示例中的doInit()
方法仅在初始化单例后设置isInitialized=true
。 但是,在您的第二个示例中,它在初始化单例之前将AtomicBoolean
实例设置为true
。 如果第二个线程在设置标志之后但在初始化完成之前获得对单例的引用,这可能是一个问题。
第二个问题不太明显:在第二个示例中设置标志后没有同步。 在初始化代码与其他线程中发生的任何事情之间没有建立发生之前的关系。 在您的第一个示例中,初始化发生在isInitialized=true
之前,而isInitialized=true
发生在任何其他线程测试之前if(!isInitialized)...
在您的第二个示例中,如果两个线程同时调用doInit()
,则原子操作确保只有其中一个可以进入初始化代码。 但是,即使获胜者纯粹是偶然地在*另一个线程开始使用单例对象之前实际完成了初始化代码,在进行初始化的第一个线程和访问该单例的第二个线程之间的关系之前仍然没有正式的发生。
*实时“之前”(又名挂钟时间)。 如果某个事件 A确实实时发生在事件 B 之前,但是这两个事件之间没有正式的发生之前的关系,那么其他线程可能会看到这两个事件的影响,就好像它们以不同的顺序发生一样.
是的,它可以。 可见性是保证。
AtomicBoolean 与 synchronized 类似,但由于 CPU 缓存的 compareAndSwap 实用程序,它被认为比同步更好。
小的区别是它不能确保同步时多个线程之间的执行顺序。
AtomicXxxx 封装了一个 volatile 所以它们基本相同,不同之处在于它提供了更高级别的操作,例如用于实现增量的 CompareAndSwap。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.