zl程序教程

您现在的位置是:首页 >  后端

当前栏目

C++单例模式(懒汉和饿汉)与线程安全

2023-09-27 14:27:45 时间

1. 饿汉模式

#include<iostream>


class singleton
{
private:
    static singleton* p;
    singleton(){}
public:
    static singleton* getInstance()
    {
        return p;
    } 
};

singleton* singleton::p = new singleton();

int main()
{
    singleton* p = singleton::getInstance();
    singleton* p2=  singleton::getInstance();
    std::cout << p << std::endl;
    std::cout << p << std::endl;
}

这是一个线程安全的实现方法,因为singleton::p在进入main函数之前就由单线程方式实例化,这也就是饿汉模式。相比之下懒汉模式就是第一次使用到类实例的时候才创建。

2. 懒汉模式

class singleton
{
private:
    static singleton* p;
    singleton(){}
public:
    static singleton* getInstance()
    {
        if(p == NULL)
        {
            p = new singleton();
            std::cout << "once" << std::endl;
        }
        else  std::cout << "not once" << std::endl;
        return p;
    } 
};

singleton* singleton::p = NULL;

3. 懒汉的线程安全问题

在多线程中,可能有多个线程同时判断p==NULL为真,所以需要加锁。

class singleton
{
private:
    static singleton* p;
    static pthread_mutex_t mutex;        
    singleton(){}
public:
    static singleton* getInstance()
    {
        pthread_mutex_lock(&mutex);
        if(p == NULL)
        {    
            p = new singleton();
        }
        pthread_mutex_unlock(&mutex);
        return p;
    } 
};

pthread_mutex_t singleton::mutex = PTHREAD_MUTEX_INITIALIZER;
singleton* singleton::p = NULL;

因为加锁是一个耗时的操作,其实只有在第一次创建实例的时候需要加锁,所以可以做一个优化:

class singleton
{
private:
    static singleton* p;
    static pthread_mutex_t mutex;        
    singleton(){}
public:
    static singleton* getInstance()
    {
        if(p == NULL)
        {
            pthread_mutex_lock(&mutex);
            if(p == NULL)
            {    
                p = new singleton();
            }
            pthread_mutex_unlock(&mutex);
        }
        return p;
    } 
};

pthread_mutex_t singleton::mutex = PTHREAD_MUTEX_INITIALIZER;
singleton* singleton::p = NULL;

 

参考链接:https://blog.csdn.net/hj605635529/article/details/70172842