C++单例模式

1、教科书里的单例模式
简单的单例模式实现起来是很简单的:只需将类的构造函数声明为private或者protect防止被外部实例化,内部保存一个private static的类指针保存唯一的实例,实例动作由一个public的类方法代劳,该方法也返回单例的唯一实例。代码实现如下:
 
 
class CSignal
{
public: 
    static CSignal *getInstanc();
protected: 
    CSignal(){};
private: 
    static CSignal *m_pInstance;
}

CSignal *CSignal::m_pInstance = NULL;

CSignal *CSiganl::getInstance()
{ 
    if(m_pInstance == NULL) 
    { 
         m_pInstance = new CSignal(); 
    } 
    return m_pInstance;
}

这是单例模式的简单实现,简单易懂,但是这不是一个完美的实现,这个方法不是线程安全的,当有两个线程同时首次调用getInstance方法且同时检测到m_pInstance的值是NULL,这两个线程就会同时构造一个实例m_pInstance,这是个严重的错误,同时,这也不是单例的唯一实现!

2、懒汉与恶汉

单例的实现大体上有两种实现方法:懒汉实现与饿汉实现。

懒汉:一个字就是懒,不到万不得已的时候不会去实例化类,也就是说第一次用到类实例的时候才会去实例化,所以上边的教科书式的写法属于懒汉实现;
饿汉:饿了就要吃东西,而且是饥不择食,所以饿汉实现就是在单例类定义的时候就进行实例化。

两种实现模式的特点与选择:
由于要进行线程同步,所以访问量比较大,或者可能访问的线程比较多时,采用饿汉实现,可以实现更好的性能。这是以空间换时间。在访问量较小的时候,采用懒汉实现,这是以时间换空间。
3、线程安全的懒汉实现

线程不安全,最直观的方法就是枷锁。

方法1:加锁的经典懒汉实现:
 
 
class CSignal
{
public:
    static pthread_mutex_t mutex; 
    static CSignal *getInstanc();
protected: 
    CSignal() 
    { 
         pthread_mutex_init(&mutex); 
    };
private: 
    static CSignal *m_pInstance;
}

CSignal*CSignal::m_pInstance=NULL;
CSignal *CSiganl::getInstance()
{ 
    if(m_pInstance == NULL) 
    {
         pthread_mutex_lock(&mutex);
         if(m_pInstance == NULL)
         {
              m_pInstance = new CSignal();
         }
         pthread_mutex_unlock(&mutex)
    }
return m_pInstance;
}


方法2:内部静态变量的懒汉实现

这个方法实现起来也很容易,在instance函数里定义一个静态实例,也可保证拥有唯一实例,在返回时只需要返回其指针就可以了。推荐使用这种方法,真的很简单,也很好用。实现代码如下:
class CSignal
{
public:
    static pthread_mutex_init(&mutex);
    static CSignal *getInstance();
    int a;
protected:
    CSignal()
    {
        pthread_mutex_init(&mutex);
    };
}

pthread_mutex_t signal::mutex;
CSignal *CSiganl::getInstance()
{
    ptread_mutex_lock(&mutex);
    static CSignal m_pInstance;
    ptread_mutex_unlock(&mutex);
    return &m_pInstance;
}

4、饿汉实现
饿汉实现是线程安全的,不用加锁,这种就是用空间换取时间,多线程可以使用这种实现。代码如下:
class CSignal
{
public:
    static CSignal *getInstance();
protected:
    CSignal(){};
private:
    static CSignal *m_pInstance;
}

CSignal *CSignal::m_pInstance = new CSignal;

CSignal *CSiganl::getInstance()
{
    return m_pInstance;
}


猜你喜欢

转载自blog.csdn.net/qq_33233768/article/details/80274614