C++设计模式之单例模式

单例模式

最简单也是被问到最多的设计模式之一,保证一个类只创建一个实例,同时提供全局访问的方法。

懒汉模式

在使用这个实例对象时才去创建,创建对象时加锁保证有且仅有一个(有线程安全问题)

实现方式

  1. 静态局部变量

  2. 互斥锁

  3. 使用C++11新特性call_once

经典的线程安全例子

复制代码
class single{
private:
    //私有静态指针变量指向唯一实例
    static single *p;

    //静态锁,是由于静态函数只能访问静态成员
    static pthread_mutex_t lock;

    //私有化构造函数
    single(){
        pthread_mutex_init(&lock, NULL);
    }
    ~single(){}

public:
    //公有静态方法获取实例
    static single* getinstance();

};

pthread_mutex_t single::lock;

single* single::p = NULL;
single* single::getinstance(){
    if (NULL == p){
        pthread_mutex_lock(&lock);
        if (NULL == p){
            p = new single;
        }
        pthread_mutex_unlock(&lock);
    }
    return p;
}

为什么要用双检测,只检测一次不行吗?

如果只检测一次,在每次调用获取实例的方法时,都需要加锁,这将严重影响程序性能。双层检测可以有效避免这种情况,仅在第一次创建单例的时候加锁,其他时候都不再符合NULL == p的情况,直接返回已创建好的实例。

局部静态变量之线程安全懒汉模式

复制代码
class single{
private:
    single(){}
    ~single(){}

public:
    static single* getinstance();

};

single* single::getinstance(){
    static single obj;
    return &obj;
}

这种方法不加锁会不会造成线程安全问题?

C++0X以后,要求编译器保证内部静态变量的线程安全性

饿汉模式

不管是否使用这个实例对象,只要类被创建出来,实例对象就被创建(无线程安全问题)

饿汉模式不需要用锁,就可以实现线程安全。原因在于,在程序运行时就定义了对象,并对其初始化。之后,不管哪个线程调用成员函数getinstance(),都只不过是返回一个对象的指针而已。所以是线程安全的,不需要在获取实例的成员函数中加锁。

c++ 复制代码
class single{
private:
    static single* p;
    single(){}
    ~single(){}

public:
    static single* getinstance();

};
single* single::p = new single();
single* single::getinstance(){
    return p;
}

//测试方法
int main(){

    single *p1 = single::getinstance();
    single *p2 = single::getinstance();

    if (p1 == p2)
        cout << "same" << endl;

    system("pause");
    return 0;
}

饿汉模式存在隐藏的问题,在于非静态对象(函数外的static对象)在不同编译单元中的初始化顺序是未定义 的。如果在初始化完成之前调用 getInstance() 方法会返回一个未定义的实例

相关推荐
LXS_35734 分钟前
Day 18 C++提高 之 STL常用容器(string、vector、deque)
开发语言·c++·笔记·学习方法·改行学it
deng-c-f2 小时前
Linux C/C++ 学习日记(53):原子操作(二):实现shared_ptr
开发语言·c++·学习
一个不知名程序员www2 小时前
算法学习入门---结构体和类(C++)
c++·算法
墨雪不会编程3 小时前
C++ string 详解:STL 字符串容器的使用技巧
java·开发语言·c++
yangpipi-3 小时前
《C++并发编程实战》第5章 C++内存模型和原子操作
android·java·c++
SunkingYang3 小时前
MFC进程间消息通信深度解析:SendMessage、PostMessage与SendNotifyMessage的底层实现与实战指南
c++·mfc·共享内存·通信·postmessage·sendmessage·进程间
XFF不秃头4 小时前
力扣刷题笔记-旋转图像
c++·笔记·算法·leetcode
王老师青少年编程4 小时前
csp信奥赛C++标准模板库STL案例应用3
c++·算法·stl·csp·信奥赛·lower_bound·标准模版库
Tim_105 小时前
【C++入门】04、C++浮点型
开发语言·c++
hkNaruto6 小时前
【C++】记录一次C++程序编译缓慢原因分析——滥用stdafx.h公共头文件
开发语言·c++