C++ 中单例的线程安全惰性构造

2024-01-23

有没有一种方法可以在 C++ 中实现单例对象:

  1. 以线程安全的方式延迟构造(两个线程可能同时是单例的第一个用户 - 它仍然应该只构造一次)。
  2. 不依赖于预先构造的静态变量(因此在构造静态变量期间单例对象本身可以安全使用)。

(我不太了解我的C++,但是在执行任何代码之前是否会初始化整型和常量静态变量(即,甚至在执行静态构造函数之前 - 它们的值可能已经在程序中“初始化”) image)?如果是这样 - 也许可以利用它来实现单例互斥体 - 这反过来又可以用来保护真正单例的创建..)


太棒了,看来我现在有几个很好的答案了(可惜我不能将 2 或 3 标记为答案)。似乎有两种广泛的解决方案:

  1. 使用 POD 静态变量的静态初始化(而不是动态初始化),并使用内置原子指令实现我自己的互斥体。这就是我在问题中暗示的解决方案类型,我相信我已经知道了。
  2. 使用其他一些库函数,例如线程一次 http://opengroup.org/onlinepubs/007908799/xsh/pthread_once.html or 升压::call_once http://www.boost.org/doc/libs/1_33_1/doc/html/call_once.html。这些我当然不知道 - 并且非常感谢发布的答案。

基本上,您要求同步创建单例,而不使用任何同步(先前构造的变量)。一般来说,不,这是不可能的。您需要一些可用于同步的东西。

至于您的其他问题,是的,可以静态初始化的静态变量(即不需要运行时代码)保证在执行其他代码之前初始化。这使得可以使用静态初始化的互斥体来同步单例的创建。

从2003年修订的C++标准开始:

具有静态存储持续时间(3.7.1)的对象应在任何其他初始化发生之前进行零初始化(8.5)。零初始化和用常量表达式初始化统称为静态初始化;所有其他初始化都是动态初始化。具有用常量表达式(5.19)初始化的静态存储持续时间的 POD 类型(3.9)的对象应在任何动态初始化发生之前进行初始化。在同一翻译单元的命名空间范围内定义并动态初始化的静态存储持续时间的对象应按照其定义在翻译单元中出现的顺序进行初始化。

If you know如果您将在其他静态对象的初始化期间使用此单例,我想您会发现同步不是问题。据我所知,所有主要编译器都在单个线程中初始化静态对象,因此静态初始化期间的线程安全。您可以将单例指针声明为 NULL,然后在使用它之前检查它是否已初始化。

但是,这假设您know您将在静态初始化期间使用此单例。标准也不能保证这一点,因此如果您想完全安全,请使用静态初始化的互斥体。

编辑:克里斯关于使用原子比较和交换的建议肯定会起作用。如果可移植性不是问题(并且创建额外的临时单例也不是问题),那么它是一个开销稍低的解决方案。

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

C++ 中单例的线程安全惰性构造 的相关文章

随机推荐

  • HTML 表单操作 method="POST" 还是 method="post"? [复制]

    这个问题在这里已经有答案了 使用非大写的 post 或大写的 POST 有什么区别吗
  • 无法将自定义转换器添加到 log4j

    下列的here http logging apache org log4j 2 x manual extending html PatternConverters 我想延长log4j通过自定义转换器 将 shiro 用户名添加到日志中 这是
  • 链接影响不同元素的 jQuery 动画

    document ready function div1 fadeIn slow div2 delay 500 fadeIn slow div3 delay 2000 fadeIn slow div4 delay 8000 fadeIn s
  • Mediatr:减少 DI 对象的数量

    我有很多命令和查询 其中大多数需要相同的接口来完成不同的事情 是否有可能如何减少我的每个处理程序都需要的这种混乱 并且一遍又一遍地重复 public class GetCoinByIdQueryHandler IRequestHandler
  • 使用 SOAP,还是不使用 SOAP?就是那个问题

    我有 3g 手机协议栈的背景 现在我需要从 Android 平板电脑与服务器进行通信 我将对接口的两侧进行编码 更新 我应该说 从 Android 多个 slate 到本地服务器 多个 然后通过卫星到单个中央主服务器 现在我想我可能不会实施
  • 生成日期范围的数据,包括数据中不存在的日期

    这是我的表结构和数据 CREATE TABLE event EventID INT 11 NOT NULL AUTO INCREMENT EventDate DATETIME DEFAULT NULL Description VARCHAR
  • 使用projectile在.dir-locals中设置flycheck-clang-include-path

    尝试设置 Flycheck clang include path 而无需包含项目的完整路径 包括使用弹丸的目录 但我收到错误 所以这有效 nil company clang arguments home user Downloads pro
  • 使用 dlopen 动态加载共享库

    我正在尝试使用 dlopen 加载 TestCode so getNumber 是我想从 TestCode so 使用的函数 但是当我加载 so 时 我无法使用该功能 它给出了分段错误 示例程序 测试头 hpp ifndef HEADER
  • 使用 dlib 面部标志裁剪面部

    我正在尝试使用 dlib 识别的面部标志来裁剪面部 右眉毛造成了问题 眉毛是平的而不是沿着眉毛的弧线 我在这里做错了什么 from imutils import face utils import imutils import numpy
  • 在 Pig 中解析复杂的 JSON 字符串

    我想在 Pig 中解析一串复杂的 JSON 具体来说 我希望 Pig 将我的 JSON 数组理解为一个包 而不是单个字符数组 使用 JsonLoader 时 我可以通过指定架构轻松完成此操作 如下所示这个问题 https stackover
  • C#中复制大量数据的方法

    我正在使用以下方法将目录的内容复制到不同的目录 public void DirCopy string SourcePath string DestinationPath if Directory Exists DestinationPath
  • onpreviewframe byte[] 到 int[]

    在预览帧中 我得到 ImageFormat RGB 565 中的字节 现在我想将此 byte 转换为 int 以便我可以进行一些像素操作 我怎么能这么做呢 附 到目前为止 我是这样做的 但似乎还没有优化 public void onPrev
  • 获取日期格式/文化

    如何指定输入字符串的哪一部分是日期和月份 如果输入是01 10 2017 这可以读作2017 年 10 月 1 日 and 2017 年 1 月 10 日 两者都是正确的 我想明确表示01是日期并且10是月份 这样无论区域设置和时间格式如何
  • ngForIn 可以在 Angular 4 中使用吗?

    我正在尝试使用迭代对象的属性 ngFor但使用in 当我尝试这样做时 Controller selector sample controller template ul li b i b obj i li ul class SampleCo
  • HTML/CSS:如何为 tr 创建滚动条

    有人可以告诉我如何为内表创建滚动条吗 内表不显示在容器内 我将容器的背景涂成黄色 桌子本身是蓝色的 我想在表格内看到一个滚动条 Source http nopaste info e51385254e html http nopaste in
  • java中如何实现国际化

    我有一堂课叫Info 我有一堆static String其中描述的变量 public class Info public static stringOne Hello public static stringTwo world 我希望访问这
  • 你明白这个僵局吗?

    我的 GUI 使用 wxPython 在里面AppLogic类我有一个工作线程 它在这个类的方法中运行 这是GUI class class GUI wx app None main window None app logic None de
  • SharpDX、DirectWrite 和 Windows 窗体

    可以使用 DirectWrite 将文本渲染到 WinForm 应用程序中的 PictureBox 中吗 我正在使用 SharpDX 并浏览了 DirectWrite 示例 试图构建最简单的工作案例 我创建了一个表单并只向其中添加了一个图片
  • 根据列值分割大型 csv 文本文件

    我的 CSV 文件有多列已排序 例如 我可能有这样的行 19980102 PLXS 10032 Q A 15 12500 15 00000 15 12500 2 19980105 PLXS 10032 Q A 14 93750 14 750
  • C++ 中单例的线程安全惰性构造

    有没有一种方法可以在 C 中实现单例对象 以线程安全的方式延迟构造 两个线程可能同时是单例的第一个用户 它仍然应该只构造一次 不依赖于预先构造的静态变量 因此在构造静态变量期间单例对象本身可以安全使用 我不太了解我的C 但是在执行任何代码之