0

The my question is related to this post.

public class SafeDCLFactory {
  private volatile Singleton instance;

  public Singleton get() {
    if (instance == null) {  // check 1
      synchronized(this) {
        if (instance == null) { // check 2
          instance = new Singleton(); // store
        }
      }
    }
    return instance;
  }
}

It is a datarace. The thread 1 can read instance (check 1) while thread 2 writes to it (store).

Why is it safe? Are store operation atomic here? What if not?

Michael
  • 41,989
  • 11
  • 82
  • 128
Gilgamesz
  • 4,727
  • 3
  • 28
  • 63
  • http://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking – D.L. May 08 '17 at 14:28
  • Possible duplicate of [Why is volatile used in this example of double checked locking](http://stackoverflow.com/questions/7855700/why-is-volatile-used-in-this-example-of-double-checked-locking) – Rafael Winterhalter May 08 '17 at 23:08
  • Writes to reference fields are always atomic. `volatile` is one way of ensuring the referenced object is safely published. – shmosel May 08 '17 at 23:16

1 Answers1

0

Technically the outer if statement is not required. It's an optimisation. If we remove that, it's a little bit easier to see what's going on.

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

In this example, we know - thanks to synchronisation - that for this instance of the factory only a single thread can be in the synchronized block at any one time. It's then safe to check-then-act. instance cannot be initialised twice.

However, there's a problem with this implementation. Every single time we try to get the instance, we need to synchronise. This really doesn't take maximum advantage of currency. It might block other threads unnecessarily.

That's why we add an extra check. The may be more than one thread trying to do initialisation simultaneously but after this brief period of time we should never need to do the synchronisation again.

public Singleton get() {
    if (instance == null) {

        //instance may actually have been created now by another thread

        synchronized(this) {
            if (instance == null) {
                instance = new Singleton();
            }
        }
    }
    return instance;
}

Is the store operation atomic here?

Yes. Assignment of references in Java is atomic.

Michael
  • 41,989
  • 11
  • 82
  • 128