The problems with the original Double-Checked Locking pattern have been well-documented: C++ and the Perils of Double-Checked Locking. I have seen the topic come up in questions on SO fairly often.
I have come up with a version that, to me, seems to solve the race condition problem of the original pattern, but does it look ok to you?
In the code below, I assume that LOCK is a properly implemented mutex type that causes a memory barrier at it's lock/unlock, and I don't attempt to deal with the deallocation of the instance, as that's not part of the pattern.
I am aware of the other possible ways to do a singleton, but that's not what I am asking for. I am specifically asking about the pattern - is the race condition solved by having the allocation outside of the mutex lock?.
template <typename T, typename LOCK> class Singleton { private: static T * instance_; static LOCK mutex; // private - inaccessible Singleton(); Singleton(const Singleton &); Singleton & operator=(const Singleton &); public: static T * get_instance() { if (instance_ == NULL) { T * temp = new T; mutex.lock(); if (instance_ == NULL) instance = temp; else delete temp; mutex.unlock(); } return instance_; } };