javabot
javabot

Reputation: 171

What is the reason for checking for nullity twice when synchronizing lazy initialization?

I came across a lazy initialization method which checks for nullity twice, before and after applying the lock. Code goes like this,

public void initializeTemplate(){
   if(tmeplate == null){
      synchronized(this){
         if(template == null){
              //initialization is done here!
         }
      }
   }
}

I was wondering what could be the reason behind checking for nullity twice? In my understanding checking before applying the lock would have sufficed, right? or am i wrong? Can anyone explain?

Upvotes: 1

Views: 79

Answers (2)

Zaid Malhis
Zaid Malhis

Reputation: 588

It is called Double-checked locking. This Wikipedia article explains it in detail.

To explain it briefly, obtaining a lock is an expensive operation, in this example it is most probably used to initialize a singleton Class in a multi threaded environment. The first if statement checks if the object is null, if the object is not null there is no need to obtain a lock to make sure that no other Thread have initialized the Object, since the object is already initialized. However, if the object is null, the Thread has to obtain a lock on the block to make sure that no other Thread is trying to initialize the Object.

The Double-checked locking is considered "broken".

Upvotes: 1

MadProgrammer
MadProgrammer

Reputation: 347214

A null check is cheap, where as synchronized is not, BUT, some other thread might have beaten you to the initialisation of the object between the first null check and the synchronized block, so you check once out side (cheap) and once instead as a precaution.

This is basically trapping a race condition, where two threads pass through the outer check, one thread will block waiting for the synchronized block to provide it the lock, while the other passes through (having secured the lock), creating an instance of the object and assigning the value to template. When it exists, the waiting thread will then have a chance to execute the code within the synchronized block, but you do a second null check to make sure you're not doing work which has already been done and breaking the single instance requirements and preventing possible reference issues

Upvotes: 3

Related Questions