单例模式懒汉模式和饿汉模式

线程安全

单例模式在单线程中,当然是安全的。但是如果在多线程中,由于并行判断,可能会导致创建多个实例。那么如何保证在多线程中单例还是只有一个实例呢?

常见的三种方式:

局部静态变量

原理和饿汉模式相似,利用static只会初始化一次的特性,并且在第一次调用的情况下才会被初始化。推荐使用

class Singleton {

private:

Singleton() { };

public:

static Singleton* getInstance() {

static Singleton *instance = new Singleton();

return instance;

}

};

饿汉模式

原理:利用static,在程序编译的时候就调用构造函数实现单例,这样做的优点是保证线程安全,但是缺点就是无论后续是否用到,在编译的时候就会创建,会导致启动性能降低。

实现方法:

class Singleton_Hungry {

public:

static Singleton_Hungry* getInstance() {

return singleton;

}

private:

Singleton_Hungry() {

cout << "Hungry creat." << endl;

}

static Singleton_Hungry* singleton;

};

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

懒汉模式

原理:利用线程锁,在获取实例的时候判断实例加上线程锁,保证判断的条件只允许一个线程操作。利用锁也可以保证单例只有一个实例。

实现方法:

#include <mutex>

std::mutex mu;

class Singleton_Lazy {

public:

static Singleton_Lazy* getInstance() {

if (singleton == NULL) {

mu.lock();//打开锁

if (singleton == NULL) {

singleton = new Singleton_Lazy();

}

mu.unlock();//关闭锁

}

return singleton;

}

private:

Singleton_Lazy() {

cout << "Lazy creat." << endl;

}

static Singleton_Lazy* singleton;

};

Singleton_Lazy* Singleton_Lazy::singleton = NULL;

实践验证

在linux系统上通过命令行g++ single.cpp --std=c++11 -lpthread编译

#include <iostream>

#include <mutex>

#include <thread>

#include <unistd.h>

using namespace std;

mutex mu;

class Singleton_Hungry {

public:

static Singleton_Hungry* getInstance() {

return singleton;

}

private:

Singleton_Hungry() {

cout << "Hungry creat." << endl;

}

static Singleton_Hungry* singleton;

};

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

class Singleton_Lazy {

private:

Singleton_Lazy() {

cout << "Lazy creat." << endl;

}

static Singleton_Lazy* singleton;

public:

static Singleton_Lazy* getInstance() {

if (singleton == NULL) {

//mu.lock();//打开锁

if (singleton == NULL) {

singleton = new Singleton_Lazy();

}

//mu.unlock();//关闭锁

}

return singleton;

}

};

Singleton_Lazy* Singleton_Lazy::singleton = NULL;

void thr(int t) {

cout << t << " pthread id: " << pthread_self() << endl;

for(int i = 0; i < 3; i++) {

Singleton_Lazy *lazy = Singleton_Lazy::getInstance();

Singleton_Hungry *hungry = Singleton_Hungry::getInstance();

cout << t << " lazy addr:" << lazy << endl;

cout << t << " hungry addr:" << hungry << endl;

}

}

int main() {

cout<<"main process id: "<<getpid()<<endl;

cout<<"main pthread id:"<< pthread_self()<<endl;

thread thread1(thr, 1);

thread thread2(thr, 2);

thread1.join();

thread2.join();

return 0;

}

结果分析

结果和预想一致,饿汉模式在程序编译阶段调用构造函数,懒汉模式在调用的时候创建,如果不加线程锁会导致创建多个实例。

【C++】保证线程安全的单例模式_c++ 线程安全单例模式-CSDN博客

相关推荐
谁似人间西林客1 天前
工业大数据实战:看中国智造如何用数据驱动效率革命
大数据·单例模式
张小姐的猫1 天前
【Linux】多线程 —— 线程池 | 单例模式 | 常见锁
linux·运维·服务器·c++·单例模式·设计模式·策略模式
Java面试题总结2 天前
双重检验锁的单例模式在高并发下的可见性问题
单例模式
珊瑚里的鱼5 天前
手撕单例模式中的饿汉模式和懒汉模式,懒汉模式还要再多加一个C++11版本的
开发语言·c++·单例模式
韩曙亮5 天前
【Flutter】Dart 单例 ( 单例模式核心规则 | 饿汉式单例 | 懒汉式单例 | 极简空安全 懒汉式单例 | 工厂构造函数单例 )
flutter·单例模式·dart·饿汉式单例·懒汉式单例·空安全·空赋值
wunaiqiezixin7 天前
如何在C++中实现一个单例模式?
c++·单例模式
basketball6167 天前
设计模式入门:1. 单例模式详解 C++实现
c++·单例模式·设计模式
bugcome_com7 天前
阿里云OSS工具类完整设计与实现:基于.NET的静态单例模式实践
阿里云·单例模式·.net·oss
JAVA9658 天前
JAVA面试-并发篇 03-使用synchronized doublecheck实现单例有什么坑
java·单例模式·面试