Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a volatile variable that is never assigned null to ever contain null?

Can in the following conceptual Java example:

public class X implements Runnable {
    public volatile Object x = new Object();

    @Runnable
    public void run() {
        for (;;) {
            Thread.sleep(1000);
            x = new Object();
        }
    }
}

x ever be read as null from another thread?

Bonus: Do I need to declare it volatile (I do not really care about that value, it suffices that sometime in the future it will be the newly assigned value and never is null)

like image 883
scravy Avatar asked Dec 17 '15 18:12

scravy


People also ask

What happens when a variable is marked as volatile?

When we declare a variable volatile, it means that all reads and all writes to this variable or from this variable will go directly into the main memory. The values of these variables will never be cached.

How does volatile variable works in Java?

The volatile modifier is used to let the JVM know that a thread accessing the variable must always merge its own private copy of the variable with the master copy in the memory. Accessing a volatile variable synchronizes all the cached copied of the variables in the main memory.

How does keyword volatile affect how a variable is handled?

The volatile keyword does not cache the value of the variable and always read the variable from the main memory. The volatile keyword cannot be used with classes or methods. However, it is used with variables. It also guarantees visibility and ordering.

What is the difference between static and volatile variable?

volatile variable value access will be direct from main memory. It should be used only in multi-threading environment. static variable will be loaded one time. If its used in single thread environment, even if the copy of the variable will be updated and there will be no harm accessing it as there is only one thread.

How do I assign a null variable to an existing variable?

!NULL can be assigned to an existing variable, undefining it and freeing its memory. The !NULL variable is equivalent to: Use the comparison operators EQ and NE to determine whether a variable has a defined value. (Null pointers and null objects have type Pointer and Objref, respectively, but have no defined values.)

How to assign a nullable value to a non-nullable value type variable?

If you want to assign a value of a nullable value type to a non-nullable value type variable, you might need to specify the value to be assigned in place of null. Use the null-coalescing operator ?? to do that (you can also use the Nullable<T>.GetValueOrDefault (T) method for the same purpose):

What is the system variable-null in C++?

The system variable !NULL is a special variable of type Undefined. Unlike a variable that is truly undefined, the value !NULL can be assigned to other variables and used in comparisons. Use any of the following to assign the value !NULL to a variable:

What is a null variable in JavaScript?

As a result, a variable set equal to !NULL can be thought of as an empty element in an array specification. Thinking of a null variable in this way makes it easy to add variables to an array without first checking to ensure that the array is defined.


2 Answers

Technically, yes it can. That is the main reason for the original ConcurrentHashMap's readUnderLock. The javadoc even explains how:

Reads value field of an entry under lock. Called if value field ever appears to be null. This is possible only if a compiler happens to reorder a HashEntry initialization with its table assignment, which is legal under memory model but is not known to ever occur.

Since the HashEntry's value is volatile this type of reordering is legal on consturction.

Moral of the story is that all non-final initializations can race with object construction.


Edit: @Nathan Hughes asked a valid question:

@John: in the OP's example wouldn't the construction have happened before the thread the runnable is passed into started? it would seem like that would impose a happens-before barrier subsequent to the field's initialization.

Doug Lea had a couple comments on this topic, the entire thread can be read here. He answered the comment:

But the issue is whether assignment of the new C instance to some other memory must occur after the volatile stores.

With the answer

Sorry for mis-remembering why I had treated this issue as basically settled: Unless a JVM always pre-zeros memory (which usually not a good option), then even if not explicitly initialized, volatile fields must be zeroed in the constructor body, with a release fence before publication. And so even though there are cases in which the JMM does not strictly require mechanics preventing publication reordering in constructors of classes with volatile fields, the only good implementation choices for JVMs are either to use non-volatile writes with a trailing release fence, or to perform each volatile write with full fencing. Either way, there is no reordering with publication. Unfortunately, programmers cannot rely on a spec to guarantee it, at least until the JMM is revised.

And finished with:

  • Programmers do not expect that even though final fields are specifically publication-safe, volatile fields are not always so.

  • For various implementation reasons, JVMs arrange that volatile fields are publication safe anyway, at least in cases we know about.

  • Actually updating the JMM/JLS to mandate this is not easy (no small tweak that I know applies). But now is a good time to be considering a full revision for JDK9.

  • In the mean time, it would make sense to further test and validate JVMs as meeting this likely future spec.

like image 136
John Vint Avatar answered Sep 24 '22 02:09

John Vint


This depends on how the X instance is published.

Suppose x is published unsafely, eg. through a non-volatile field

private X instance;
...
void someMethod() {
    instance = new X();
}

Another thread accessing the instance field is allowed to see a reference value referring to an uninitialized X object (ie. where its constructor hasn't run yet). In such a case, its field x would have a value of null.

The above example translates to

temporaryReferenceOnStack = new memory for X // a reference to the instance
temporaryReferenceOnStack.<init> // call constructor
instance = temporaryReferenceOnStack;

But the language allows the following reordering

temporaryReferenceOnStack = new memory for X // a reference to the instance
instance = temporaryReferenceOnStack;
temporaryReferenceOnStack.<init> // call constructor

or directly

instance = new memory for X // a reference to the instance
instance.<init> // call constructor

In such a case, a thread is allowed to see the value of instance before the constructor is invoked to initialize the referenced object.

Now, how likely this is to happen in current JVMs? Eh, I couldn't come up with an MCVE.


Bonus: Do I need to declare it volatile (I do not really care about that value, it suffices that sometime in the future it will be the newly assigned value and never is null)

Publish the enclosing object safely. Or use a final AtomicReference field which you set.

like image 37
Sotirios Delimanolis Avatar answered Sep 24 '22 02:09

Sotirios Delimanolis