设计模式——单例模式

The Redefine Team Lv3

单例模式(Singleton Pattern)

简述

单例模式是C++中常见的一种设计模式,它要求整个程序中只能存在一个实例,一般通过禁用构造和拷贝(这里的禁用指的是不对外暴露接口,而不是使用delete关键字删除),并提供唯一接口创建static实例来实现。根据实例对象的创建时机的不同,分为饿汉式和懒汉式单例模式:

饿汉式

代码实现

所谓饿汉式,指的是在程序启动时就创建对象实例,具体的实现代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Singleton{
private:
static Singleton _instance;
Singleton(){}
~Singleton(){}
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

// 因为是单例模式
// 所以不能通过对象实例进行函数调用
// 所以声明为static支持通过类进行访问
static Singleton& getInstance(){
return _instance;
}
};

Singleton Singleton::_instance;

代码分析

饿汉模式天生是线程安全的,因为静态对象在启动时就会创建;但是如果对象太大,而程序有长时间未使用,可能会带来较大的资源消耗

懒汉式

代码实现

懒汉式有几种实现方式,这是因为最简单的实现版本具有线程安全问题,所以后续推出了几种优化方案,下面一一介绍一下:

初始版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Singleton{
private:
static Singleton* _instance;
Singleton(){}
~Singleton(){}
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
static Singleton* getInstance(){
if(!_instance){
_instance = new Singleton();
}
return _instance;
}
};
Singleton* Singleton::_instance = nullptr;

因为单例模式的对象实例和程序的生命周期相同,所以无需在析构函数中显式的delete掉new出来的对象

这里的实现是有线程安全问题的,如果两个线程同时进入Line 11的内存分配逻辑,会导致内存分配两个Singleton对象,而其中一个会被覆盖,导致内存泄露问题;

双重锁检查机制(DCL, Double-Check Lock)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <mutex>

class Singleton {
private:
Singleton() {}
~Singleton() {}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

static Singleton* instance;
static std::mutex mtx;

public:
static Singleton* getInstance() {
if (!instance) { // 第一重检查
std::lock_guard<std::mutex> lk(mtx);
if (!instance) { // 第二重检查
instance = new Singleton();
}
}
return instance;
}
};
// 定义静态成员
Singleton* Singleton::instance = nullptr;
std::mutex Singleton::mtx;

第一重检查:性能优化,避免即使在无条件竞争的情况下依然需要申请锁,带来不必要的性能开销(锁竞争和上下文切换)

第二重检查:正确性保证,在锁保护的前提下再次确认未创建状态,避免多个线程重复执行new Singleton()

C++11局部静态变量(Meyers’ Singleton)

这是在C++11之后支持的线程安全版本的懒汉式的单例模式,实现更为简单:

1
2
3
4
5
6
7
8
9
10
11
12
13
class Singleton{
private:
Singleton(){}
~Singleton(){}
public:
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;

static Singleton& getInstance(){ // C++11保证线程安全
static Singleton _instance;
return _instance;
}
};
  • 标题: 设计模式——单例模式
  • 作者: The Redefine Team
  • 创建于 : 2025-05-20 00:00:00
  • 更新于 : 2025-06-03 14:50:30
  • 链接: https://redefine.ohevan.com/2025/05/20/单例模式/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论