[英]Is it necessary to make `AtomicBoolean` also `volatile`?
My understanding: Declaring a variable volatile
guarantees the visibility for other threads about writes to that variable.我的理解:声明一个变量
volatile
可以保证其他线程对该变量的写入可见性。 Essentially, every write
to volatile variable happens-before subsequent reads
.本质上,对 volatile 变量的每次
write
都发生在后续reads
之前。
I understand the atomicity of AtomicBoolean.compareAndSet()
and how it provides the atomicity of read+write
operation that volatile
doesn't.我了解
AtomicBoolean.compareAndSet()
的原子性以及它如何提供volatile
所没有的read+write
操作的原子性。 But I don't see any doc providing visibility guarantee by AtomicBoolean
like the following:但我没有看到任何文档提供
AtomicBoolean
的可见性保证,如下所示:
write
by AtomicBoolean.compareAndSet()
will eventually be visible to subsequent AtomicBoolean.get()
and AtomicBoolean.compareAndSet()
by other threads. AtomicBoolean.compareAndSet()
的每次成功write
最终都会被其他线程后续AtomicBoolean.get()
和AtomicBoolean.compareAndSet()
看到。 But, I keep seeing code labelled as thread-safe
which are like this,但是,我一直看到标记为
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
}
}
}
Shouldn't the variable executing
also declared volatile
, like private static volatile AtomicBoolean executing = new AtomicBoolean(false);
不应该
executing
的变量也声明为volatile
,例如private static volatile AtomicBoolean executing = new AtomicBoolean(false);
? ? So the visibility guarantee needed by
AtomicBoolean
is achieved?那么
AtomicBoolean
所需要的可见性保证就实现了吗?
Is it necessary to make
AtomicBoolean
alsovolatile
?是否有必要使
AtomicBoolean
也volatile
?
No.不。
In the example, executing
is declared as static final
, so it will be initialized once at class initialization time and safely published to any other code that needs it.在示例中,
executing
被声明为static final
,因此它将在 class 初始化时初始化一次,并安全地发布到需要它的任何其他代码。
This behavior is guaranteed because there is a happens-before between a classes initialization completing (normally) and any subsequent use of any static variable declared by the class.这种行为是有保证的,因为在类初始化完成(通常)和任何后续使用由 class 声明的任何 static 变量之间存在发生之前。 The fact that the variable is also
final
excludes any subsequent assignments to the static that would negate the happens-before .变量也是
final
的事实排除了对 static 的任何后续分配,这些分配将否定发生之前。
You would only need to declare executing
as volatile
if something could assign a new value to it after initialization.如果某些东西可以在初始化后为其分配新值,则只需要将
executing
声明为volatile
。 That's not possible here without doing some nasty reflection.如果不进行一些令人讨厌的反思,这是不可能的。 (And the JLS states that if you do that kind of thing to change a
final
, the memory model guarantees do not apply.) (并且 JLS 声明,如果你做那种事情来改变
final
,memory model 保证不适用。)
You would get a similar effect if executing
was final
but an instance field rather than a static
field.如果
executing
是final
的但实例字段而不是static
字段,您将获得类似的效果。 The reasoning is slightly different, but it is also explicitly mentioned in the JLS.推理略有不同,但在 JLS 中也明确提及。
Finally, the Java syntax does not allow you to combine volatile
and final
modifiers.最后,Java 语法不允许您组合
volatile
和final
修饰符。 That combination doesn't make sense.这种组合没有意义。
We cannot use the below code我们不能使用下面的代码
private static volatile final AtomicBoolean executing = new AtomicBoolean(false);
Usage of volatile and final together is invalid . volatile 和 final 一起使用是无效的。 As stated by @RealSkeptic var which would never change (final) need not have volatile.
正如@RealSkeptic 所说,永远不会改变(最终)的 var 不需要 volatile。 Volatile is used for those vars whose values gets changed in runtime by one or more thread.
Volatile 用于那些值在运行时被一个或多个线程更改的变量。
//Happy learning //快乐学习
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.