Use of volatile in singleton double null check implementation in java

眉间皱痕 提交于 2019-12-13 06:28:44

问题


I want to know what is use of making Instance variable as volatile in double null check implementation of Singleton. Because as per my understanding synchronize block provide happens before implicitly. No two threads can access that synchronized block concurrently and while exiting from synchronized block, thread write all its local cached data to main memory. I search a lot but still i have doubts in this implementation. Please explain correct use.

private volatile Singleton INSTANCE; 
public Singleton get() { 
    if (INSTANCE == null) { 
        synchronized (this) { 
            if (INSTANCE == null) { 
                INSTANCE = new Singleton(); 
            } 
        } 
    } 
    return INSTANCE; 
}

In above double checking code. What may b the issue if i dont make my instance as volatile. Because when first thread enter in synchronize block, no other thread will get access to that block. And when first thread leaves that block. Object will be created and due to happens before property, latest value of instance will be written in main memory. So why volatile is important in this scenario?

Here's a link (Is there any need to add volatile keyword to guarantee thread-safe singleton class in java?) of similar question. But answers are not very clear. I don't think in above given scenario any kind of JVM optimization can cause breaking of happens before of synchronize block


回答1:


volatile is important here because of the internals of the JVM on the bytecode level. The statement

INSTANCE = new Singleton()

is on bytecode level actually something like that:

1. INSTANCE = create Singleton object
2. call constructor of INSTANCE

if INSTANCE is volatile the JVM guarantees you that 1+2 are executed as an atomic operation from the point of view of other threads, e.g. by storing the instance on the stack before storing it in the field. If it is not volatile it might be that other threads can already see the reference to Singleton before the constructor has been called. Thus these threads might see an incomplete object.




回答2:


Because as per my understanding synchronize block provide happens before implicitly. No two threads can access that synchronized block concurrently and while exiting from synchronized block

It is correct if you have a simple lazy singleton implementation. In that every access to the variable goes through syncronized block.

private Singleton INSTANCE;

public static synchronized Singleton getInstance() {
  if (INSTANCE == null) {
    INSTANCE = new Singleton();
  }
  return INSTANCE;
}

But once you have a safe double-check lazy implementation, not every code path goes through synchronized block. The second call to this method will read the variable from a local field without entering synchronized block and the INSTANCE has to be volatile.

private volatile Singleton INSTANCE;

public Singleton get() {
  if (INSTANCE == null) {
    synchronized (this) {
      if (INSTANCE == null) {
        INSTANCE = new Singleton();
      }
    }
  }
  return INSTANCE;
}

You can read more about safe publishing in this article.



来源:https://stackoverflow.com/questions/41906611/use-of-volatile-in-singleton-double-null-check-implementation-in-java

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!