应用场景:在整个系统中只能有一个实例对象

 

 1 class Singleton
 2 {
 3     private:
 4         Singleton();
 5         ~Singleton();
 6         Singleton(const Singleton&);
 7         Singleton&operator=(const Singleton&);
 8     public:
 9         static Singleton *getinstance();
10         static Singleton *m_instance;
11 }
12 Singleton *Singleton::m_instance=NULL;

case1:单线程,此时不会出现线程安全问题

1 Singleton *Singleton::getinstance()
2 {
3     if(m_instance==NULL)
4     {
5         m_instance=new Singleton();
6     }
7         return m_instance;
8 }

case2:多线程

 1     //线程安全,但是锁的代价高
 2 Singleton *Singleton::getinstance()
 3 {
 4     Lock lock;
 5     if(m_instance==NULL)
 6     {
 7         m_instance=new Singleton();
 8     }
 9     return m_instance;
10 }

   如果多个线程只是读操作,会影响效率

改进版,双检查锁

Singleton* Singleton::getinstance()
{
    if(m_instance==NULL)      //避免都是读操作时加锁,代价过高
    {   
        Lock lock;
        if(m_instance==NULL)       //这行不能省,如果省略,会出现多个实例
            m_instance=new Singleton();
    }
    return m_instance;
}

  这个双检查锁版本看似完美,但是还有漏洞。

  m_instane=new Singleton();被编译器拆分成三个动作:step1、调用malloc分配空间;step2、m_instance指针指向新分配好的空间,step3、调用构造函数初始化。如果线程1在执行到第二步以后,线程2进入函数开始判断m_instance是否为空,发现不为空,立即返回m_instance,但是此时m_instance并没有初始化完成。由此可见双检查锁欺骗了线程2。