[4] [对象性能] ( 1 ) 单例模式 Singleton
总结
- 场景
资源分享(数据库)
配置管理
日志管理
对象工厂
c++例子
- 经典的magic static版本 (c++11之后才支持)
(这个版本是线程安全的, 原因是其他线程会等到第一个线程完成instance的构建)
更多参考:
https://zhuanlan.zhihu.com/p/344714248
#include <iostream>
class Singleton {
public:
static Singleton &getInstance() {
// 在首次调用时进行初始化,且线程安全
static Singleton instance;
return instance;
}
Singleton(const Singleton &) = delete;
void operator=(const Singleton &) = delete;
void doSomething() {
std::cout << "Singleton instance is doing something." << std::endl;
}
private:
Singleton() = default;
};
int main() {
Singleton &instance1 = Singleton::getInstance();
instance1.doSomething();
// 尝试实例化第二个对象,实际上该对象和第一个是同一个
Singleton &instance2 = Singleton::getInstance();
instance2.doSomething();
// 编译器将阻止下面的行,因为复制构造函数和赋值操作符重载已被删除
// Singleton instance3 = instance1;
// Singleton instance4;
// instance4 = instance1;
return 0;
}
- 线程安全版本
锁的代价过高, 不推荐
Singleton* Singleton::getInstance() {
Lock lock;
if (m_instance == nullptr) {
m_instance = new Singleton();
}
return m_instance;
}
- 双检查锁版本
编译器存在reorder行为,
这个版本的内存读写不安全.
Singleton* Singleton::getInstance() {
if(m_instance==nullptr){
Lock lock;
if (m_instance == nullptr) {
m_instance = new Singleton();
}
}
return m_instance;
}
- 用atomic实现正确的双检查锁单例模式
#include <iostream>
#include <atomic>
#include <mutex>
class Singleton {
public:
// 获取单例实例的静态方法
static Singleton *getInstance() {
Singleton *temp = instance.load(std::memory_order_relaxed);
// 创建一个内存屏障, 确保在屏障之前对变量temp的读取操作, 不会被移到屏障之后.
std::atomic_thread_fence(std::memory_order_acquire);
// 双重检查锁定模式(double-checked locking pattern) 确保多线程创建单例对象的安全性
if (temp == nullptr) {
std::lock_guard<std::mutex> lock(mutex);
// 读取
temp = instance.load(std::memory_order_relaxed);
if (temp == nullptr) {
temp = new Singleton();
// 释放内存屏障
std::atomic_thread_fence(std::memory_order_release);
// 写入
instance.store(temp, std::memory_order_relaxed);
std::cout << "new singleton instance." << std::endl;
}
}
return temp;
}
// 删除拷贝构造函数和赋值操作符重载,以确保单例类不会被复制
Singleton(const Singleton &) = delete;
void operator=(const Singleton &) = delete;
// 释放单例对象
static void destroyInstance() {
Singleton *temp = instance.load();
if (temp != nullptr) {
// Lock to prevent multiple threads from concurrently destroying the instance
std::lock_guard<std::mutex> lock(mutex);
// Set the instance pointer to nullptr and get the previous value
temp = instance.exchange(nullptr);
if (temp != nullptr) {
delete temp;
std::cout << "delete singleton instance." << std::endl;
}
}
}
// 其他成员函数和成员变量
void doSomething() {
std::cout << "Singleton instance is doing something." << std::endl;
}
private:
// 将默认构造函数设为私有,防止外部类实例化该类
Singleton() = default;
// 使用 std::atomic 来保证线程安全和避免重排序
static std::atomic<Singleton *> instance;
static std::mutex mutex;
};
// 在类外初始化静态成员
std::atomic<Singleton *> Singleton::instance(nullptr);
std::mutex Singleton::mutex;
int main() {
Singleton *instance1 = Singleton::getInstance();
instance1->doSomething();
Singleton *instance2 = Singleton::getInstance();
instance2->doSomething();
printf("%p, %p \n",
static_cast<void *>(instance1), static_cast<void *>(instance2));
instance1->destroyInstance();
instance2->destroyInstance();
return 0;
}
java例子1
未完成...
浙公网安备 33010602011771号