0

I have a code snippet that I don't understand I will highlight the bit that confused me.

private static final Object lock = new Object();
private static volatile YourObject instance;

public static YourObject getInstance() {
    YourObject r = instance;    // <---------- This bit, why do we assign it here ? 
    if (r == null) {
        synchronized (lock) {    // What is the benefit of this lock in here
            r = instance;        // assuming instance is null which will pass the first if ( r == null, what do we assign it again ?? I don't get the idea of this step at all. 
            if (r == null) {  
                r = new YourObject();
                instance = r;
            }
        }
    }
    return r;
}

I have seen https://www.journaldev.com/1377/java-singleton-design-pattern-best-practices-examples but there implementation looks like this, which doesn't have two assignments.

public static ThreadSafeSingleton getInstanceUsingDoubleLocking(){
    if(instance == null){
        synchronized (ThreadSafeSingleton.class) {
            if(instance == null){
                instance = new ThreadSafeSingleton();
            }
        }
    }
    return instance;
}
David Conrad
  • 15,432
  • 2
  • 42
  • 54
Frank Dax
  • 108
  • 7

1 Answers1

2
    YourObject r = instance;    // <---------- This bit, why do we assign it here ?

It is easier to reason about local variables, which you really want here. Also there is overhead in reading volatile variables that may not be merged by the optimiser.

    synchronized (lock) {    // What is the benefit of this lock in here

This is the lock that prevents multiple threads creating and assigning different instances of YourObject simultaneously.

        r = instance;        // assuming instance is null which will pass the first if ( r == null, what do we assign it again ?? I don't get the idea of this step at all. 

instance may have changed between the first read for the null check and the lock being successfully acquired.

Anyway, don't use double-checked locking - it's very confusing and there's probably better ways.

Tom Hawtin - tackline
  • 145,806
  • 30
  • 211
  • 305
  • so what is the best way to create singleton for multi threading ? – Frank Dax Oct 27 '20 at 21:30
  • 1
    "Anyway, don't use double-checked locking." <-- This. It's *hard* to get right, to the extent that Josh Bloch got the example of DCL wrong when he wrote *Effective Java* 3rd Ed. – Andy Turner Oct 27 '20 at 21:31
  • @FrankDax Firstly, avoid singletons and global state in general. If you absolutely have to `static final`. – Tom Hawtin - tackline Oct 27 '20 at 21:31
  • 1
    @FrankDax in order of preference: 1) eager initialization: a plain old `static final ThreadSafeSingleton INSTANCE = new ThreadSafeSingleton();`; 2) a single-element enum; 3) a [lazy holder](https://en.wikipedia.org/wiki/Initialization-on-demand_holder_idiom). – Andy Turner Oct 27 '20 at 21:32
  • @AndyTurner So it is. Took me a while. I was about to ask to see that if `field` changes between the `if` statements, the new value doesn't get assigned. (I `this.wait();` in `computeFieldValue` is unlikely, but would also "work"). – Tom Hawtin - tackline Oct 28 '20 at 03:18
  • (I should probably add for any future readers: Only applies to *Effective Java* 3rd Ed. **first four printings** (and the PDF I have). I believe later versions have a corrected Double Check Locking example. **But still don't use it.**) – Tom Hawtin - tackline Oct 28 '20 at 07:53