Sam
Sam

Reputation: 2432

When Singleton is not Singleton?

I was reading a blog which discussed about When Singleton is not Singleton.

In one of the cases of which Author tries to explain shows how double checked locking can also be a failure when implemented on Singleton.

// Double-checked locking -- don't use
public static MySingleton getInstance() {
    if (_instance==null) {
      synchronized (MySingleton.class) {
        if (_instance==null) {
           _instance = new MySingleton();
        }
      }
    }
}

For the above code block Author says:

"In this situation, we intend to avoid the expense of grabbing the lock of the singleton class every time the method is called. The lock is grabbed only if the singleton instance does not exist, and then the existence of the instance is checked again in case another thread passed the first check an instant before the current thread."

Can someone help me explaining what exactly this means?

Upvotes: 2

Views: 1181

Answers (3)

nanofarad
nanofarad

Reputation: 41281

I'll try to talk it through.

The synchronized block takes time to enter as it requires cross-thread coordination. We'll try to avoid entering it if needed.

Now, if we are working with multiple threads, if the object already exists, let's just return it, as methods will synchronize themselves against threading race conditions internally. We can do this before entering a synchronized block as if it was created, it was created. The constructor is already designed so a partially-constructed object cannot be returned, as specified by the memory model design.

If the singleton object doesn't exist yet, we need to create one. But what if while we were checking another thread created it? We'll use synchronized to ensure no other threads hold it. Now, once we enter, we check again. If the singleton was created by another thread, let's return it since it exists already. If we didn't do this, a thread could get its singleton and do something to it and we'd just steamroller over its changes and effects.

If not, let's lock it and return a new one. By holding the lock, we now protect the singleton from the other side. Another thread waits for the lock, and noticing it's been created(as per the inner null comparison) returns the existing one. If we didn't acquire the lock, threads would both steamroller over changes, and find their changes destroyed as well. Please note that the code block in your post is incomplete. It would need to return _instance if any of the null checks returned false, using else blocks.

Now, if we were in a single-threaded environment this would not have been important. We could just use:

public static MySingleton getInstance() {
    if (_instance==null) {
        _instance = new MySingleton();
    }
    else return _instance;
}

With newer versions, java uses this behavior in many cases, as part of its libraries, checking if a lock is needed before taking time to acquire it. Before, it either failed to acquire the lock(bad, data loss) or acquired it immediately(bad, more potential for slowdown and deadlock).

You should still implement this yourself in your own classes for thread safety.

Upvotes: 4

Juned Ahsan
Juned Ahsan

Reputation: 68715

I have found on wikipedia, the best of explanation of different Singleton implentations, their flaws and what is the best. Follow this link:

http://en.wikipedia.org/wiki/Singleton_pattern

Hope it helps!

Upvotes: 1

user207421
user207421

Reputation: 310893

He doesn't explain how it can fail in that quote. He is just explaining double-checked locking. He probably refers elsewhere to the fact that double-checked locking itself didn't work prior to Java 1.5. But that's a long time ago.

Upvotes: 3

Related Questions