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.
RSS feed for comments on this post. TrackBack URI
Powered by WordPress
There are issues with this:
http://en.wikipedia.org/wiki/Double-checked_locking
Specifically, compilers may optimize the pInstance in such a way that pInstance will point to a partially constructed object.
Comment by EJ — November 21, 2007 @ 3:13 am
A simple alternative is to use a function such as pthread_once on POSIX or the InitOnce methods in Vista which will run a method a single time regardless of how many threads call it.
As EJ notes above, double checked locking will fail on some compilers even if volatile is used. You need to lock for all access to the pointer.
Comment by Scottt — August 27, 2008 @ 4:37 am
Not positively sure about C++, but Java allows something really simpler:
public class MyClass
{
private final static instance = new MyClass();
public static MyClass getInstance()
{
return instance;
}
}
This ensures the static field is initialized only once. An alternative, if startup code is more complex, is to used a static constructor :
public class MyClass
{
private final static instance;
static {
// some global initialization stuff…
instance = new MyClass();
}
public static MyClass getInstance()
{
return instance;
}
}
This is not to start a C++/Java war ; I’ve made more Java than C++, and want to learn ;)
Comment by Al — October 6, 2008 @ 9:50 am
That is one of the things that led to the revisions in the Java memory model a few years ago. The new C++ standard has the notion to address this sort of thing.
Here’s what a quick google search turns up on the problem (in C++)
http://www.devarticles.com/c/a/Cplusplus/C-plus-in-Theory-Why-the-Double-Check-Lock-Pattern-Isnt-100-ThreadSafe/
http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html
Comment by Bill Robertson — October 10, 2008 @ 12:01 am
As someone mentioned earlier, this becomes problematic as you’re running into the anti-pattern of double checked locking. This idiom has been tried again and again, only to realize that it does not work.
I know you can get around it by using ‘volatile’ in Java and possibly the same thing in C++.
Comment by Mahmoud Abdelkader — October 10, 2008 @ 5:02 pm