Does the thread show the effect of the constructor as it happens after a volatile reference is set to a reference to a newly created object?

I read it here -

When thread A writes to a volatile variable and then thread B reads the same variable, the values ​​of all variables that were visible to A before writing to the volatile variable become visible to B after reading the volatile variable. So, because of perspective memory visibility, writing a volatile variable is like exiting a synchronized block and reading a volatile variable like entering a synchronized block

Below is a snippet from here and the article is from 2001 when the semantics of the volatile keyword is different.

class SomeClass {
  private Resource resource = null;
  public Resource getResource() {
    if (resource == null) {
      synchronized {
        if (resource == null) 
          resource = new Resource();
      }
    }
    return resource;
  }
}

      

A double checked lock is committed if the link is made mutable.

private volatile Resource resource = null;

      

But is it necessary to make the member fields of the Resource class also volatile to ensure thread safety?

EDIT:

The author mentions in the same article that - Volatile doesn't mean what you think, either

A commonly suggested nonfix is ​​to declare the resource field SomeClass as mutable. However, while JMM prevents volatile variables from being reordered with respect to each other and ensures that they are flushed to main memory immediately, it still allows reading and writing volatile variables that need to be reordered with respect to non-volatile reads and writes. This means that if all the Resource Fields are also volatile - thread B can still perceive the constructor effect as it happens after the resource is set to a reference to the newly created resource.

This means that Double Checked Locking was a penalty prior to JDK 5 given the Resource Fields are also volatile or the class itself is immutable . Please suggest.

+3


source to share


1 answer


In some old JVM, dated 2001, the meaning of the keyword was volatile

sometimes misunderstood, so the implementation didn't function as it should - this is the reason behind the statements in the second quote in your question, one from an article from 2001 - that volatile is nonfix for DCL.

quote from: http://www.javamex.com/tutorials/synchronization_volatile_java_5.shtml

Since Java 5, access to a volatile variable creates a memory barrier: it effectively synchronizes all cached copies of variables with main memory, just like entering or exiting a synchronized block that is synchronized on a given object. Typically this has little impact on the programmer, although sometimes it makes mutable a good option for posting a safe object. The infamous double check antipattern blocking actually becomes valid in Java 5 if the reference is declared mutable.

Since Java 5 things have changed and writing / reading to a field volatile

cannot be reordered with a non-volatile read / write, so whatever is specified in the code must be done before a write to volatile is actually done before that write. According to your snippet: If the fields of a class member are Resource

immutable, you don't need to make them volatile

to make them read-safe by other threads. If other threads (other than the ones building and initializing the instance fields Resource

) can modify these memeber fields, then you need to make them thread safe (e.g. marking them as volatile

) - this is just an example of a simple memory barrier, it might not be enough). Considering your example with substitution for use volatile

:

class SomeClass {
  private volatile Resource resource = null;
  public Resource getResource() {
    if (resource == null) {
      synchronized {
        if (resource == null) 
          resource = new Resource();
      }
    }
    return resource;
  }
}

      



The constructor is Resource()

fully executed before an instance is assigned to a mutable field. Reading streams will display all the memory that was written by the instantiating thread - so all intialization is visible, which means publishing the instance Resource

is thread safe.

To be clear:

The statement made by @BrianGoetz in a 2001 article that field labeling is volatile ...

... still allows reordering reads and writes of volatile variables with respect to non-volatile read and write

no longer runs in modern JVMs (JVM> = Java5)

DISCLAIMER Often we use the term memory box when we talk about synchronization, but many sources state that it is indeed instruction reordering that is prevented by such barriers, so a typical memory barrier simply ensures that everything in the code claimed to have been executed before memory barrier points (e.g. entering a synchronized block, writing to a volatile variable) was actually executed before your program reaches the memory point . (for example, you know that if you read a reference to a volatile variable it won't be posted until the constructor actually finishes and returns the form initialization). There are no flashes in the main memory in sync- CPU cache is written to main memory in other cases, what makes the memory visible to other threads in a multi-core processor is the hardware cache coherency

+3


source







All Articles