c++ - 在 C++ 中,多线程线程安全惰性构造

  显示原文与译文双语对照的内容

是否可以在 C++ 中实现一个单独的对象,即:

  • 以线程安全的方式以线程安全方式构造( 两个线程可能同时成为单一用户的第一个用户- 它仍然应该只构建一次) 。
  • 不依赖于预先构建的static 变量。

如果我的C++ 不太清楚,那么在执行任何代码之前,整型和常量变量的初始化是否都是先初始化的? 如果这样- 也许可以利用它实现单一互斥体- 这又可以用来保护真正的单例的创建。

很好,看来我现在有了几个好的答案。 似乎有两种解决方案:

  • 在一个 POD static 变量中使用 static 初始化( 与动态初始化相对应),并使用内置的原子指令实现我自己的互斥。 这是我在问题中暗示的解决方案类型,我相信我已经知道了。
  • 使用其他库函数,如 pthread_once 或者 boost::call_once 。 这些我当然不知道- 我非常感谢所发布的答案。
时间: 原作者:

基本上,你要求在不使用任何同步( 。以前构造的变量)的情况下同步创建一个单例。 一般来说,这是不可能的。 你需要一些可以用于同步的东西。

对于其他问题,是,可以静态初始化的static 变量( 例如 。 在执行其他代码之前,不需要保证任何运行时代码都被。 这样就可以使用静态初始化互斥体来同步单例的创建。

从 C++ 标准的2003修订版中:

具有 static 存储持续时间( 3.7.1 )的对象应在它的他初始化发生前零初始化( 8.5 ) 。 零初始化和使用常数表达式初始化为 static 初始化;所有其他初始化都是动态初始化。 使用常量表达式初始化的POD类型的对象( 使用常量表达式初始化) 在进行任何动态初始化之前都应该初始化。 同一翻译单元中的命名空间范围中定义的static 存储持续时间的对象应按它的定义中的定义初始化。

如果你不知道,在初始化其他 static 对象期间将使用这个单例,我想你会发现同步是一个非问题的问题。 最好的是,所有主要编译器都在单线程中初始化 static 对象,因这里在 static 初始化期间线程安全。 可以将单例指针声明为空,然后在使用它之前检查它是否已经初始化。

但是,这假设你不知道在 static 初始化期间将使用这里单例。 这也不是由标准保证的,因这里如果你想要完全安全,请使用静态初始化互斥。

编辑:建议chris使用原子compare-and-swap一定会工作的。 如果可移植性不是问题( 创建额外的临时单例并不是问题),那么它的开销就会稍微低一点。

...