0

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:

  1. Every successful write by AtomicBoolean.compareAndSet() will eventually be visible to subsequent AtomicBoolean.get() and AtomicBoolean.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?

Alanpatchi
  • 1,177
  • 10
  • 20
  • 1
    `volatile` is for changes in the *variable*. That is, if anything else is assigned to `executing`. If it is only assigned in the initializer, and never changed, marking it as `volatile` is irrelevant. What you want is the visibility of the content of the object that it refers to, not the visibility of the variable itself. – RealSkeptic Jun 21 '20 at 09:34
  • @RealSkeptic thanks. Now it makes sense. So if one wants to make the visibility of changes in an object, one would have to make the object mutable but thread-safe, and thats what `AtomicBoolean` can do? – Alanpatchi Jun 21 '20 at 09:42

2 Answers2

3

Is it necessary to make AtomicBoolean also 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.

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.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
2

We cannot use the below code

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

Usage of volatile and final together is invalid. As stated by @RealSkeptic var which would never change (final) need not have volatile. Volatile is used for those vars whose values gets changed in runtime by one or more thread.

//Happy learning