是否有必要使"原子布尔值"也"易变"?



我的理解:声明变量volatile保证其他线程对该变量的写入的可见性。从本质上讲,对易失变量的每个write都发生在后续reads之前。

我了解AtomicBoolean.compareAndSet()的原子性以及它如何提供volatile没有read+write操作的原子性。但是我没有看到任何文档通过如下所示AtomicBoolean提供可见性保证:

  1. 每个成功的writebyAtomicBoolean.compareAndSet()最终都会对后续AtomicBoolean.get()可见,并由其他线程AtomicBoolean.compareAndSet()

但是,我一直看到标记为thread-safe的代码是这样的,

// default false so that first-thread that execute() can enter the logic block
private static final  AtomicBoolean executing = new AtomicBoolean(false);

public void execute() {
if (executing.compareAndSet(false, true)) {  // check if the executing is previously false and if so update it to true
try {
// thead-safe code, i.e only one thread guaranteed to execute at any point of time time
} finally {
executing.set(false); // executing thread now re-sets the test value
}
}
}

变量executing不应该也像private static volatile AtomicBoolean executing = new AtomicBoolean(false);一样声明为volatile吗?那么AtomicBoolean所需的能见度保证是否实现了?

是否有必要使AtomicBooleanvolatile

不。

在示例中,executing被声明为static final,因此它将在类初始化时初始化一次,并安全地发布到任何其他需要它的代码。

此行为是有保证的,因为在类初始化完成(正常(和类声明的任何静态变量的任何后续使用之间有一个先行。变量也final排除了对静态的任何后续赋值,这些赋值会否定之前发生的情况

您只需要将executing声明为volatile,如果某些东西可以在初始化后为其分配新值。 如果不做一些令人讨厌的反思,这是不可能的。 (JLS指出,如果你做这种事情来改变final,内存模型保证不适用。


如果executingfinal只是实例字段而不是static字段,您将获得类似的效果。 推理略有不同,但在 JLS 中也明确提到。


最后,Java 语法不允许你组合volatilefinal修饰符。 这种组合没有意义。

我们不能使用以下代码

private static volatile final AtomicBoolean executing = new AtomicBoolean(false);

易失性和最终性一起使用是无效的。正如@RealSkeptic var 所说,永远不会改变(最终(的变量不需要具有波动性。易失性用于那些其值在运行时被一个或多个线程更改的变量。

快乐学习

相关内容

  • 没有找到相关文章