My understanding: Declaring a variable volatile
guarantees the visibility for other threads about writes to that variable. Essentially, every write
to volatile variable happens-before subsequent reads
.
I understand the atomicity of AtomicBoolean.compareAndSet()
and how it provides the atomicity of read+write
operation that volatile
doesn’t. But I don’t see any doc providing visibility guarantee by AtomicBoolean
like the following:
- Every successful
write
byAtomicBoolean.compareAndSet()
will eventually be visible to subsequentAtomicBoolean.get()
andAtomicBoolean.compareAndSet()
by other threads.
But, I keep seeing code labelled as thread-safe
which are like this,
// 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);
? So the visibility guarantee needed by AtomicBoolean
is achieved?
Advertisement
Answer
Is it necessary to make
AtomicBoolean
alsovolatile
?
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.
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. The fact that the variable is also final
excludes any subsequent assignments to the static that would negate the happens-before.
You would only need to declare executing
as volatile
if something could assign a new value to it after initialization. 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.)
You would get a similar effect if executing
was final
but an instance field rather than a static
field. The reasoning is slightly different, but it is also explicitly mentioned in the JLS.
Finally, the Java syntax does not allow you to combine volatile
and final
modifiers. That combination doesn’t make sense.