面向对象设计与分析40讲(17)双重检查锁定(double-checked locking)范式
2023-12-25 00:01:15
双重检查锁定(也称为“双重检查锁定优化”)是一种用于减少获取锁的开销的软件设计模式。它通过在获取锁之前测试锁定条件(即“锁提示”)来实现。只有在锁定条件检查表明需要锁定时才会进行锁定操作。
#include <atomic>
#include <mutex>
class Singleton {
public:
static Singleton* GetInstance();
private:
Singleton() = default;
static std::atomic<Singleton*> s_instance;
static std::mutex s_mutex;
};
Singleton* Singleton::GetInstance() {
Singleton* p = s_instance.load(std::memory_order_acquire); // A
if (p == nullptr) { // 1st check
std::lock_guard<std::mutex> lock(s_mutex);
p = s_instance.load(std::memory_order_relaxed);
if (p == nullptr) { // 2nd (double) check
p = new Singleton();
s_instance.store(p, std::memory_order_release); // B
}
}
return p;
}
memory_order_acquire主要保证两个事情:
- 相同原子变量的release操作此处可见
- 创建一个同步(synchronization)边界,任何读写都不会被重排到该操作之前
memory_order_release主要保证两个事情:
- 内存写操作对acquire相同原子变量的线程可见
- 创建一个同步(synchronization)边界,任何读写都不会被重排到该操作之后
即假设A、B两个线程同时运行于A、B点,B的release操作对线程A可见。同时p = new Singleton()的读写操作不会被重排到B点之后。
C++ 11提供了基于该范式实现的基础设施std::once_flag和std::call_once:
#include <mutex>
#include <optional> // Since C++17
// Singleton.h
class Singleton {
public:
static Singleton* GetInstance();
private:
Singleton() = default;
static std::optional<Singleton> s_instance;
static std::once_flag s_flag;
};
// Singleton.cpp
std::optional<Singleton> Singleton::s_instance;
std::once_flag Singleton::s_flag{};
Singleton* Singleton::GetInstance() {
std::call_once(Singleton::s_flag,
[]() { s_instance.emplace(Singleton{}); });
return &*s_instance;
}
文章来源:https://blog.csdn.net/HandsomeHong/article/details/135188107
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!