Writing a thread safe singleton has its difficulties. One of them is making sure that the dynamic creation of the inner singleton object is thread safe, while locking as few mutexes as possible.
Let’s first look at a naive Instance static member function:
MyClass* MyClass::Instance()
{
if (!pInstance) {
pInstance = new ....
}
return pInstance;
}
Obviously, it is not thread safe. Two threads can cause the instance to be created twice. A natural solution is just to use a mutex:
MyClass* MyClass::Instance()
{
// Mutex is freed when the local lock object is destructed
mutex lock("Mutex0");
if (!pInstance) {
pInstance = new ....
}
return pInstance;
}
Assuming that MyClass::Instance() is called very frequently, the last implementation will slow down the execution, since locking (especially a mutex) can be very very slow. However, locking is only needed for the instance’s creation, and not for every time we are trying to get the instance. Following is a very simple improvement:
MyClass* MyClass::Instance()
{
if (!pInstance) {
mutex lock("Mutex0");
if (!pInstance) {
pInstance = new ....
}
}
return pInstance;
}
Every caller who enters the function after pInstance was allocated will not lock the mutex. Callers who enter the function before the instance was created are still synchronized with the mutex.
Powered by WordPress