当前位置: 首页 > news >正文

面向对象设计与分析40讲(17)双重检查锁定(double-checked locking)范式

双重检查锁定(也称为“双重检查锁定优化”)是一种用于减少获取锁的开销的软件设计模式。它通过在获取锁之前测试锁定条件(即“锁提示”)来实现。只有在锁定条件检查表明需要锁定时才会进行锁定操作。

#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); // Aif (p == nullptr) { // 1st checkstd::lock_guard<std::mutex> lock(s_mutex);p = s_instance.load(std::memory_order_relaxed);if (p == nullptr) { // 2nd (double) checkp = 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;
}

相关文章:

  • PostgreSQL 作为向量数据库:入门和扩展
  • redhat 8 安装openstack
  • Elasticsearch之常用DSL语句
  • 数字人私人定制
  • Python将普通图像转化为栅格影像
  • python3遇到Can‘t connect to HTTPS URL because the SSL module is not available.
  • m3u8网络视频文件下载方法
  • HDMI2.1输入转4Port MIPI/LVDS输出,嵌入式SPI闪存固件存储,VR和AR应用首选国产芯片方案-LT6911GXC
  • 设计模式——行为型模式
  • 成为一名FPGA工程师:面试题与经验分享
  • 智慧园区物联综合管理平台感知对象管理能力简述
  • JavaScript:函数隐含对象arguments/剩余参数. . .c/解构赋值
  • javafx写一个文档编辑器
  • Unity中Shader裁剪空间推导(在Shader中使用)
  • 2024最新前端React面试题:React18相比react17有哪些主要更新?
  • ES6指北【2】—— 箭头函数
  • [译] React v16.8: 含有Hooks的版本
  • Android交互
  • HTML中设置input等文本框为不可操作
  • HTTP--网络协议分层,http历史(二)
  • JavaScript实现分页效果
  • Java读取Properties文件的六种方法
  • JS笔记四:作用域、变量(函数)提升
  • Koa2 之文件上传下载
  • Spring技术内幕笔记(2):Spring MVC 与 Web
  • Vim 折腾记
  • 不上全站https的网站你们就等着被恶心死吧
  • 初识 webpack
  • 理解IaaS, PaaS, SaaS等云模型 (Cloud Models)
  • 使用 @font-face
  • 一起来学SpringBoot | 第三篇:SpringBoot日志配置
  • 硬币翻转问题,区间操作
  • 用Node EJS写一个爬虫脚本每天定时给心爱的她发一封暖心邮件
  • 运行时添加log4j2的appender
  • zabbix3.2监控linux磁盘IO
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​人工智能书单(数学基础篇)
  • ​总结MySQL 的一些知识点:MySQL 选择数据库​
  • (2)(2.10) LTM telemetry
  • (二)换源+apt-get基础配置+搜狗拼音
  • (删)Java线程同步实现一:synchronzied和wait()/notify()
  • (完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子
  • (原創) 如何讓IE7按第二次Ctrl + Tab時,回到原來的索引標籤? (Web) (IE) (OS) (Windows)...
  • **python多态
  • ./indexer: error while loading shared libraries: libmysqlclient.so.18: cannot open shared object fil
  • .NET 6 在已知拓扑路径的情况下使用 Dijkstra,A*算法搜索最短路径
  • .NET CF命令行调试器MDbg入门(二) 设备模拟器
  • .NET 将多个程序集合并成单一程序集的 4+3 种方法
  • .NET/C# 利用 Walterlv.WeakEvents 高性能地定义和使用弱事件
  • .NET6 命令行启动及发布单个Exe文件
  • .Net高阶异常处理第二篇~~ dump进阶之MiniDumpWriter
  • .net中生成excel后调整宽度
  • @media screen 针对不同移动设备
  • @Service注解让spring找到你的Service bean
  • [C# 网络编程系列]专题六:UDP编程