1、简要描述
单例模式(Singleton Pattern)是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点。单例模式的典型应用就是任务队列。
实现思路:私有化它的构造函数,以防止外界创建单例类的对象;使用类的私有静态指针变量指向类的唯一实例,并用一个公有的静态方法获取该实例。
单例模式在实际应用中有两种常见的实现方式:懒汉模式(Lazy Initialization)和饿汉模式(Eager Initialization)。这两种模式主要在实例的创建时机和线程安全方面有所不同,总结如下:
特点 | 懒汉模式 | 饿汉模式 |
---|---|---|
实例创建时机 | 第一次使用时 | 类加载时 |
线程安全 | 需要处理线程安全问题 | 天生线程安全 |
资源使用效率 | 资源使用效率高,不使用时不创建 | 可能会浪费资源,类加载时即创建 |
实现难度 | 需要增加线程同步机制,复杂度高 | 实现简单,不需要额外的线程同步 |
2、饿汉模式
饿汉模式就是在类加载的时候立刻进行实例化,这样就得到了一个唯一的可用对象。关于这个饿汉模式的类的定义如下:
// 饿汉模式
class TaskQueue
{
public:
// = delete 代表函数禁用, 也可以将其访问权限设置为私有
TaskQueue(const TaskQueue& obj) = delete;
TaskQueue& operator=(const TaskQueue& obj) = delete;
static TaskQueue* getInstance() {
return m_taskQ;
}
private:
TaskQueue() = default;
static TaskQueue* m_taskQ;
};
// 静态成员初始化放到类外部处理
TaskQueue* TaskQueue::m_taskQ = new TaskQueue;
int main()
{
TaskQueue* obj = TaskQueue::getInstance();
return 0;
}
3、懒汉模式
懒汉模式是在类加载的时候不去创建这个唯一的实例,而是在需要使用的时候再进行实例化。使用静态局部对象解决懒汉模式的线程安全问题,代码如下:
class TaskQueue
{
public:
// = delete 代表函数禁用, 也可以将其访问权限设置为私有
TaskQueue(const TaskQueue& obj) = delete;
TaskQueue& operator=(const TaskQueue& obj) = delete;
static TaskQueue* getInstance() {
static TaskQueue taskQ;
return &taskQ;
}
private:
TaskQueue() = default;
};
int main()
{
TaskQueue* queue = TaskQueue::getInstance();
return 0;
}
在上述程序中定义了一个静态局部队列对象,并且将这个对象作为了唯一的单例实例。使用这种方式之所以是线程安全的,是因为在C++11标准中有如下规定,并且这个操作是在编译时由编译器保证的:如果指令逻辑进入一个未被初始化的声明变量,所有并发执行应当等待该变量完成初始化。