// singleton_dclp_atomic.h
#pragma once
#include <atomic>
#include <mutex>
template <typename T>
class Singleton {
public:
static T& instance() {
T* tmp = instance_.load(std::memory_order_acquire); // ① 第一次检查(无锁)
if (tmp == nullptr) {
std::lock_guard<std::mutex> lock(mtx_);
tmp = instance_.load(std::memory_order_relaxed); // ② 第二次检查(持锁)
if (tmp == nullptr) {
tmp = new T(); // ③ 真正构造
instance_.store(tmp, std::memory_order_release);
}
}
return *tmp;
}
Singleton(const Singleton&) = delete;
Singleton& operator=(const Singleton&) = delete;
private:
static std::atomic<T*> instance_;
static std::mutex mtx_;
};
// ---------- 定义静态成员 ----------
template <typename T>
std::atomic<T*> Singleton<T>::instance_{nullptr};
template <typename T>
std::mutex Singleton<T>::mtx_;
使用
#include "singleton_dclp_atomic.h"
#include <iostream>
struct Foo {
Foo() { std::cout << "Foo constructed\n"; }
void hello() { std::cout << "hello singleton\n"; }
};
int main() {
Singleton<Foo>::instance().hello();
}
| 行 | 作用 |
|---|---|
std::atomic<T*> | 避免编译器/CPU 指令重排,保证“写指针”前对象已完全构造 |
memory_order_acquire / release | 建立 happens-before 关系,防止读到半初始化对象 |
| 第一次检查 | 无锁快速路径,已初始化时直接返回引用 |
| 第二次检查 | 持锁后再次检查,防止并发线程重复 new |
delete 拷贝 | 禁止拷贝,确保全局唯一 |
C++11 以后,双检锁 + 原子指针 仍是展示“无锁快速路径 + 内存屏障”最经典范例;
日常工程直接用局部静态即可,无需手写。

656

被折叠的 条评论
为什么被折叠?



