C++11 中的双重检查锁单例

2024-03-03

以下单例实现是否没有数据竞争?

static std::atomic<Tp *> m_instance;
...

static Tp &
instance()
{
    if (!m_instance.load(std::memory_order_relaxed))
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (!m_instance.load(std::memory_order_acquire))
        {
            Tp * i = new Tp;
            m_instance.store(i, std::memory_order_release);    
        }    
    }

    return * m_instance.load(std::memory_order_relaxed);
}

Is the std::memory_model_acquire负载操作是否多余?是否可以通过将加载和存储操作切换为来进一步放松它们std::memory_order_relaxed?在这种情况下,获取/释放语义是std::mutex足以保证其正确性,或者进一步std::atomic_thread_fence(std::memory_order_release)还需要确保构造函数的内存写入发生在宽松存储之前?然而,使用围栏是否等同于让商店拥有memory_order_release?

EDIT:感谢约翰的回答,我想出了以下应该没有数据竞争的实现。尽管内部负载可能根本不是原子的,但我决定保留宽松的负载,因为它不会影响性能。与始终具有获取内存顺序的外部负载相比,thread_local 机制将访问实例的性能提高了大约一个数量级。

static Tp &
instance()
{
    static thread_local Tp *instance;

    if (!instance && 
        !(instance = m_instance.load(std::memory_order_acquire)))
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (!(instance = m_instance.load(std::memory_order_relaxed)))
        {
            instance = new Tp; 
            m_instance.store(instance, std::memory_order_release);    
        }    
    }
    return *instance;
}

我认为这是一个很好的问题,约翰·卡尔斯贝克有正确的答案。

然而,需要明确的是,惰性单例最好使用经典的 Meyers 单例来实现。它保证了 C++11 中的正确语义。

§ 6.7.4

...如果控制进入 变量初始化时同时声明,并发执行需等待 完成初始化。 ...

Meyer 的单例是首选,因为编译器可以积极优化并发代码。如果编译器必须保留 a 的语义,它会受到更多限制std::mutex。此外,迈耶的单例是2 lines而且几乎不可能出错。

这是迈耶单例的经典示例。简单,优雅,又在c++03中破碎。但 c++11 简单、优雅、功能强大。

class Foo
{
public:
   static Foo& instance( void )
   {
      static Foo s_instance;
      return s_instance;
   }
};
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++11 中的双重检查锁单例 的相关文章

  • 捕获 .aspx 和 .ascx 页面中的异常

    问题说明了一切 请看以下示例代码 ul li li ul
  • C# 中的 Stack<> 实现

    我最近一直在实现递归目录搜索实现 并且使用堆栈来跟踪路径元素 当我使用 string Join 连接路径元素时 我发现它们被颠倒了 当我调试该方法时 我查看了堆栈 发现堆栈内部数组中的元素本身是相反的 即最近 Push 的元素位于内部数组的
  • 无法继承形状

    为什么我不能使用继承 a 的类Shapes class http msdn microsoft com en us library ms604615 28v vs 90 29 我需要延长Rectangle具有一些方法的类 但我想以与使用相同
  • strlen() 编译时优化

    前几天我发现你可以找到编译时strlen使用这样的东西 template
  • 在 Mono 中反序列化 JSON 数据

    使用 Monodroid 时 是否有一种简单的方法可以将简单的 JSON 字符串反序列化为 NET 对象 System Json 只提供序列化 不提供反序列化 我尝试过的各种第三方库都会导致 Mono Monodroid 出现问题 谢谢 f
  • 如何修复错误:“检测到无法访问的代码”

    我有以下代码 private string GetAnswer private int CountLeapYears DateTime startDate return count String answer GetAnswer Respo
  • 防止控制台应用程序中的内存工作集最小化?

    我想防止控制台应用程序中的内存工作集最小化 在Windows应用程序中 我可以这样做覆盖 SC MINIMIZE 消息 http support microsoft com kb 293215 en us fr 1 但是 如何在控制台应用程
  • 用于在标头更改时重新编译的简单 C 项目的示例 makefile

    有谁有完整的 makefile 可以执行以下操作 如果 HEADER 文件发生更改 则重建项目 cpp 文件在 makefile 中列出 头文件未在 makefile 中列出 头文件允许与 cpp 文件具有不同的名称 部分cpp文件没有头文
  • Makefile 和 .Mak 文件 + CodeBlocks 和 VStudio

    我对整个 makefile 概念有点陌生 所以我对此有一些疑问 我正在 Linux 中使用 CodeBlocks 创建一个项目 我使用一个名为 cbp2mak 的工具从 CodeBlocks 项目创建一个 make 文件 如果有人知道更好的
  • C# 获取数据表中所有重复行的计数

    我通过运行存储过程来填充数据集 并且从数据集中填充数据表 DataSet RawDataSet DataAccessHelper RunProcedure storedprocedureName this will just return
  • 如何防止 Blazor NavLink 组件的默认导航

    从 Blazor 3 1 Preview 2 开始 应该可以防止默认导航行为 https devblogs microsoft com aspnet asp net core updates in net core 3 1 preview
  • Unity c# 四元数:将 y 轴与 z 轴交换

    我需要旋转一个对象以相对于现实世界进行精确旋转 因此调用Input gyro attitude返回表示设备位置的四元数 另一方面 这迫使我根据这个四元数作为默认旋转来计算每个旋转 将某些对象设置为朝上的简单方法如下 Vector3 up I
  • ASP.NET Core 中间件与过滤器

    在阅读了 ASP NET Core 中间件之后 我对何时应该使用过滤器以及何时应该使用中间件感到困惑 因为它们似乎实现了相同的目标 什么时候应该使用中间件而不是过滤器 9频道有一个关于此的视频 ASP NET 怪物 91 中间件与过滤器 h
  • C++ 指针引用混淆

    struct leaf int data leaf l leaf r struct leaf p void tree findparent int n int found leaf parent 这是 BST 的一段代码 我想问一下 为什么
  • 每个客户端一个线程与线程服务器的排队线程模型之间的相对优点?

    假设我们正在构建一个线程服务器 旨在在具有四个核心的系统上运行 我能想到的两种线程管理方案是每个客户端连接一个线程和一个排队系统 正如第一个系统的名称所暗示的那样 我们将为每个连接到服务器的客户端生成一个线程 假设一个线程始终专用于程序的主
  • 如何编写一个接受 int 或 float 的 C 函数?

    我想用 C 语言创建一个扩展 Python 的函数 该函数可以接受 float 或 int 类型的输入 所以基本上 我想要f 5 and f 5 5 成为可接受的输入 我认为我不能使用if PyArg ParseTuple args i v
  • 声明一个负长度的数组

    当创建负长度数组时 C 中会发生什么 例如 int n 35 int testArray n for int i 0 i lt 10 i testArray i i 1 这段代码将编译 并且启用 Wall 时不会出现警告 并且似乎您可以分配
  • 如果找不到指定的图像文件,显示默认图像的最佳方式?

    我有一个普通的电子商务应用程序 我将 ITEM IMAGE NAME 存储在数据库中 有时经理会拼错图像名称 为了避免 丢失图像 IE 中的红色 X 每次显示产品列表时 我都会检查服务器中是否有与该产品相关的图像 如果该文件不存在 我会将其
  • ContentDialog Windows 10 Mobile XAML - 全屏 - 填充

    我在项目中放置了一个 ContentDialog 用于 Windows 10 上的登录弹出窗口 当我在移动设备上运行此项目时 ContentDialog 未全屏显示 并且该元素周围有最小的填充 在键盘上可见 例如在焦点元素文本框上 键盘和内
  • 如何在 ASP.NET Core 中注入泛型的依赖关系

    我有以下存储库类 public class TestRepository Repository

随机推荐

  • 自定义 STL 序列的最小嵌套 typedef 集?

    应在满足序列概念的自定义 STL 类中定义的最小嵌套 typedef 集是什么 自定义序列应兼容 std back insert iterator http www sgi com tech stl front insert iterato
  • 从 Apple Developer Portal 中删除开发者证书

    我错误地在我的 Apple 开发者帐户上创建了开发者证书 现在我想从门户中删除它 但我不喜欢任何方法来删除它 您能给我一个如何从苹果开发者门户删除证书的想法 建议吗 如果您错误地创建了证书或者想要重置证书 您可以从 Apple Develo
  • 如何连接位置数据(纬度、经度)

    我必须数据集 一个包含某个位置 经纬度 即测试 另一个包含纽约市所有邮政编码的纬度 经度信息 即 test2 test lt structure list trip count 1 10 dropoff longitude c 73 959
  • AWS Lambda 无法删除 Amazon S3 对象

    我正在尝试创建一个 AWS Lambda 函数 该函数处理上传到第一个存储桶的文件 然后将其保存到第二个存储桶 然后删除输入文件 问题是 当我尝试删除文件时 我得到了 message Access Denied code AccessDen
  • 复制的 std::list 中的垃圾

    我的图形类看起来像 class Graph public typedef unsigned int size type typedef std list
  • 具有静态存储持续时间的对象构造函数中的 std::cout 使用

    使用安全吗std cout在 C 98 C 03 中具有静态存储持续时间的对象的构造函数中 由此看来answer https stackoverflow com a 8785008 1608835它不是 但它不包含标准中的任何引用 只有在
  • 在另一个 for 循环中使用 for 循环

    我正在尝试以彩虹色打印文件 但是我有一个问题 这是我的代码 color 91 93 92 96 94 95 with open sys argv 1 as f for i in f read for c in color print 033
  • 哈希图与数组性能

    当数组的索引已知时 使用数组或 HashMap 是否 性能方面 更好 请记住 示例中的 对象数组 映射 只是一个示例 在我的实际项目中 它是由另一个类生成的 因此我不能使用单独的变量 数组示例 SomeObject objects new
  • PHP 和 mySQL 单引号还是双引号?

    我没有看到使用单引号或双引号有任何区别 我何时或为什么应该使用第一个而不是后者 我读过一些关于 SQL 我应该使用单打的文章 为什么 您应该使用单引号和mysql real escape string http php net manual
  • 在表格行上使用 Flexbox?

    我找不到任何快速答案 使用起来爽吗display flex 在表行上 tr 元素 感觉不对 但如果没有兼容性问题我会这样做 这是我正在谈论的内容的代码笔 https codepen io connorv pen boEYOB editors
  • 如何在不擦除 \perl\site\lib\ 和 \perl\site\bin\ 的情况下升级 Strawberry Perl?

    我下载了 5 12 3 安装程序来升级 5 12 1 安装 安装5 12 3后 我之前安装的cpan模块消失了 这是预期的行为吗 我应该在升级之前备份我的库以防止这种情况发生吗 我会声称这不应该是预期的行为 The site目录不是标准发行
  • 如何使 JsonResult 返回数组数组(不带字段名)而不是对象数组?

    我有一个日期 值对的 IEnumerable 列表 我将其作为 Json 列表返回以进行浮动 但是 当我调用 JsonResult 时 结果如下所示 Date date1 Value value1 Date date2 Value valu
  • Angular 1.2 的 debugInfoEnabled

    Angular 1 3引入了一个新的debugInfoEnabled https docs angularjs org api ng provider 24compileProvider debugInfoEnabled调用该方法可以提高性
  • 这是使用 jQuery 解析 XML 时的错误吗?

    好的 我会尝试尽可能简单地解释这一点 我正在尝试使用 jQuery 解析通过 Web 服务获得的 XML 一切都按其应有的方式进行 直到我注意到看在上帝的份上 我无法解析名为 image 的节点 长话短说 2小时后 我注意到 问题出在标签名
  • 如何解决文档未定义错误?

    我收到此错误 我以为是因为 node js 但我不确定 我该如何解决它 Running node c Users Lenovo Desktop projectjs index js c Users Lenovo Desktop projec
  • 理解 Haskell as 模式

    我正在通读 Real World Haskell 并试图理解 as 模式 摘自书中 第 4 章 suffixes a gt a suffixes xs xs xs suffixes xs suffixes 这本书解释了 符号 将变量 xs
  • 如何替换特定文本行中的特定单词[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 好的 我有这个 yaml 文件 我想替换一个字符串 socialspy true 用字符串 socialspy false 但我不知道
  • 如何以编程方式判断安装了哪些 Outlook 插件以及它们是否已启用?

    如何确定安装了哪些 Outlook COM 或 PIA 插件以及它们是否已启用 我怎样才能获得这些信息 以及文件版本 1 如果您想从另一个 Outlook 加载项内部访问此信息 您可以使用 Application ComAddins 对象
  • LDAP 过滤器 - 查找特定 OU 的所有用户

    我遇到了问题LDAP Search Filter 我需要检索的是特定的所有用户LDAP组即OU Staff OU Users OU Accounts DC test DC local 我的搜索是 objectCategory user OU
  • C++11 中的双重检查锁单例

    以下单例实现是否没有数据竞争 static std atomic