0

Below is the code snippet for thread safe design. Why are we checking for instance = null both before and inside the synchronized block? Isn't it sufficient to check for it outside?

// double locking is used to reduce the overhead of the synchronized method
public static ThreadSafeSingleton getInstanceDoubleLocking() {
    if (instance == null) {
        synchronized (ThreadSafeSingleton.class) {
            if (instance == null) {
                instance = new ThreadSafeSingleton();
            }
        }
    }
    return instance;
}
Vimal
  • 77
  • 1
  • 9

4 Answers4

1

Its called Double check in Singleton pattern
Let's assume the First thread enters in the method check if the instance is null if it is, It will acquire the lock and start creating the object.

Assume that while the first thread is still creating the instance (maybe a heavy object), at the same Time another thread may enter the method it checks the instance is yet null because first thread is still creating the resource and has the lock , now first threads create the object releases the lock and second thread enters the synchronized block and check that the instance is now not null condition fails and it comes out of the method. Thus only on instance is present. more details

https://www.java67.com/2015/09/thread-safe-singleton-in-java-using-double-checked-locking-pattern.html

Amit Kumar Lal
  • 5,537
  • 3
  • 19
  • 37
1

Checking inside is sufficient, however, as the comment indicates; this method first checks in a racy manner if the instance is initialized, to avoid some synchronizations: if instance is witnessed to be not null outside, and if all threads obey the protocol that the only possible change is instance becoming non-null, then it it safe not to synchronize to return instance once it has been observed non-null.

Checking outside is not sufficient (let's say from thread A), because, even if instance is indeed null outside; it may have been initialized by another thread until the inside check is reached by A. Without the second check, instance may be created twice and ooops two singletons!

Effective Java by Joshua Block discusses this pattern as well as its variants.

Clément Hurlin
  • 440
  • 3
  • 11
1

It isn't sufficient to check only in the outside of the block, as it could be that the test passes but then another thread sets the value of instance before the synchronized block is reached. If that happened then you could potentially have the singleton newed twice by two different threads, then have two different parts of the runtime point at two different singleton objects.

The code as written is thread safe. It appears to be making a very small performance optimisation that would make sense if this method is called extremely frequently or if your runtime environment is on embedded hardware.

damon140
  • 11
  • 1
  • 5
1

outer if (instance == null) is for performance and inner if (instance == null) is ensuring the singleton creation.

Suppose we dont have any if (instance == null) the our code become as below,

// double locking is used to reduce the overhead of the synchronized method
public static ThreadSafeSingleton getInstanceDoubleLocking() {

        synchronized (ThreadSafeSingleton.class) {
               // any number of thread can enter this block one by one and can create new instance
                instance = new ThreadSafeSingleton();

        }

    return instance;
}

threads can enter one by one but only one thread can create object after that other threads can enter the block but can not create instance but unnecessary they are entering into syncronization block. So putting outer if condition prevent later threads to enter synchronization block.

public static ThreadSafeSingleton getInstanceDoubleLocking() {

        synchronized (ThreadSafeSingleton.class) {
    // threads can enter one by one but only one thread can create object after that other threads can enter the block but can not create instance but unnecessary they are entering into syncronization block. So putting outer if condition prevent later threads to enter synchronization block.
            if (instance == null) {
                instance = new ThreadSafeSingleton();
            }
        }

    return instance;
}
madhepurian
  • 271
  • 1
  • 13