I would like to use singleton pattern in a multithreaded program. Double-checked locking method seems suitable for its efficiency, however this method is broken and not easy to get right.
I write the following code hoping that it works as an alternative to the double-checked locking. Is it a correct implementation of a thread-safe singleton pattern?
static bool created = false;
static Instance *instance = 0;
Instance *GetInstance() {
if (!created) {
Lock lock; // acquire a lock, parameters are omitted for simplicity
if (!instance) {
instance = new Instance;
} else {
created = true;
}
}
return instance;
}
The first call will create Instance. The second call will set created to true. And finally, all other calls will return a well initialized instance.
http://voofie.com/content/192/alternative-to-double-checked-locking-and-the-singleton-pattern/
No, this doesn’t help. If the writes to
createdandinstanceare non-atomic then there is no guarantee that the values are visible to a thread that doesn’t lock the mutex.e.g. Thread 1 calls
getInstance.createdisfalse, andinstanceis null, so it locks the mutex and creates a new instance. Thread 1 callsgetInstanceagain, and this time setscreatedtotrue. Thread 2 now callsgetInstance. By the vagaries of the processor’s memory management it seescreatedastrue, but there is no guarantee that it also seesinstanceas non-null, and even if it does there is no guarantee that the memory values for the pointed-to instance are consistent.If you’re not using atomics then you need to use mutexes, and must use them for all accesses to a protected variable.
Additional info: If you are using mutexes, then the compiler and runtime work together to ensure that when one thread releases a mutex lock and another thread acquires a lock on that same mutex then the second thread can see all the writes done by the first. This is not true for non-atomic accesses, and may or may not be true for atomic accesses, depending on what memory ordering constraints the compiler and runtime guarantee for you (with C++11 atomics you can choose the ordering constraints).