Avoid locking in Singleton

The Singleton is a useful Design Pattern which allows only one instance of your class. Singleton is implemented by declaring static instance of the object reference within the class

class MySingleton {
static MySingleton *instance;
MySingleton() {
//...
}

public:
MySingleton* getInstance() {
return instance;
}

}

static MySingleton::instance= new MySingleton();

If singleton object is created during loading time itself, no locking is required. But in case of lazy loading, it needs to be guarded with a mutex to avoid multiple object instantiation.

MySingleton* getInstance() {

 //acquire mutex
if (NULL == instance) {
instance = new MySingleton();

 }

  //release mutex
return instance;
}

Every request to getInstance() includes mutex overhead.In order to avoid mutex overhead, double checked locking pattern can be used.

// Double-checked locking -- don't use
MySingleton* getInstance() {
if (NULL == instance) {
//acquire mutex
if (NULL==instance) {
instance = new MySingleton();
}
//release mutex
}
}

This method is not 100% safe because of compiler optimizations and may lead to undefined behavior which is hard to debug. Another technique(safe to use) is to use atomic operations and local variable as specified below.


MySingleton* getInstance() {
MySingleton *localRef = new MySingleton();

  int ret = testandset(&instance, 0, localRef);

  //note testandset function returns old value stored in the variable.
if (0==ret) {
return instance;
}
//some other thread had initialized this.

  delete localRef;

  return instance;
}

Advertisements

SOLID Design Principles

SOLID is acronym introduced by Robert C Martin, which stands for five basic principles of object oriented programming/design.

Single Responsibility Principle:
Every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class.

Open Closed Principle:
Software entities (classes, modules) should be open for extension, but closed for modification.

Liskov Substitution Principle:
If S is a subtype of T, then objects of type T in a program may be replaced with objects of type S without altering any of the desirable properties of that program.

Interface Segregation Principle:
Split interfaces which are very large into smaller and more specific ones so that clients will only have to know about the methods that are of interest to them.

Dependency Inversion Principle:
Decouple high-level components from low-level components such that reuse with different low-level component implementations becomes possible.