我的理解是:声明变量volatile可以保证其他线程对该变量的写入的可见性。本质上,对易失性变量的每个write都会发生--在后续的reads之前。
我理解AtomicBoolean.compareAndSet()的原子性,以及它如何提供volatile没有的read+write操作的原子性。但是,我没有看到任何文档提供AtomicBoolean的可见性保证,如下所示:
AtomicBoolean.compareAndSet()的每个成功的write最终都将通过其他线程对后续的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不也应该声明volatile,比如private static volatile AtomicBoolean executing = new AtomicBoolean(false);吗?那么,AtomicBoolean所需要的可见性保证就达到了吗?
发布于 2020-06-21 09:40:35
是否有必要使
AtomicBoolean也成为volatile?
不是的。
在本例中,executing被声明为static final,因此它将在类初始化时初始化一次,并安全地发布到任何其他需要它的代码中。
这种行为是有保证的,因为在类初始化之前,完成(通常)和类声明的任何静态变量的任何后续使用之间都会发生这种情况。变量也是final,这一事实排除了对静态的任何后续赋值,这些赋值都会否定以前发生的情况。
只有在初始化后可以为executing指定一个新值时,才需要将它声明为volatile。在这里不做一些恶心的反思是不可能的。( JLS指出,如果您做了这样的事情来更改final,则内存模型保证不适用。)
如果executing是final,而是实例字段而不是static字段,则会得到类似的效果。理由略有不同,但在JLS中也有明确提到。
最后,Java语法不允许您组合volatile和final修饰符。这种组合没有意义。
发布于 2020-06-21 09:40:19
我们不能使用以下代码
private static volatile final AtomicBoolean executing = new AtomicBoolean(false);同时使用易失性和final是无效的。正如@RealSkeptic所指出的,它永远不会改变(最终),不需要有易失性。vars的值在运行时被一个或多个线程更改。
//快乐学习
https://stackoverflow.com/questions/62496707
复制相似问题