前言
  前段时间在网上看到了个的面试题,大概意思是如何在不使用锁和C++11的情况下,用C++实现线程安全的Singleton。
  看到这个题目后,第一个想法是用Scott Meyer在《Effective C++》中提到的,在static成员函数中构造local static变量的方法来实现,但是经过一番查找、思考,才明白这种实现在某些情况下是有问题的。本文主要将从基本的单线程中的Singleton开始,慢慢讲述多线程与Singleton的那些事。
  单线程
  在单线程下,下面这个是常见的写法:
template<typename T>
class Singleton
{
public:
static T& getInstance()
{
if (!value_)
{
value_ = new T();
}
return *value_;
}
private:
Singleton();
~Singleton();
static T* value_;
};
template<typename T>
T* Singleton<T>::value_ = NULL;
  在单线程中,这样的写法是可以正确使用的,但是在多线程中不行了。
  多线程加锁
  在多线程的环境中,上面单线程的写法会产生race condition从而产生多次初始化的情况。要想在多线程下工作,容易想到的是用锁来保护shared variable了。下面是伪代码:
template<typename T>
class Singleton
{
public:
static T& getInstance()
{
{
MutexGuard guard(mutex_)  // RAII
if (!value_)
{
value_ = new T();
}
}
return *value_;
}
private:
Singleton();
~Singleton();
static T*     value_;
static Mutex  mutex_;
};
template<typename T>
T* Singleton<T>::value_ = NULL;
template<typename T>
Mutex Singleton<T>::mutex_;
  这样在多线程下能正常工作了。这时候,可能有人会站出来说这种做法每次调用getInstance的时候都会进入临界区,在频繁调用getInstance的时候会比较影响性能。这个时候,为了解决这个问题,DCL写法被聪明的先驱者发明了。