c++ - 可以(由编译器)使用多少线程来初始化全局对象(在函数 main 之前)

标签 c++ multithreading initialization singleton

问题的措辞可能有误,但思路很简单。不保证不同翻译单元中全局对象的初始化顺序。如果一个应用程序由两个翻译单元组成——编译器是否可以生成初始化代码来启动两个线程以在这些翻译单元中创建全局对象?这个问题类似于thisthis但我认为答案与问题不符。 我将重新表述这个问题 - 如果一个程序有多个全局对象 - 它们的构造函数是否总是从同一个线程调用(考虑到用户代码不会在 main 之前启动任何线程)?

为了使这个问题更实际 - 考虑这样一种情况:多个全局对象分散在多个翻译单元中,并且每个对象都在构造函数中递增单个全局计数器。如果不能保证它们在单线程中执行,则必须同步对计数器的访问。对我来说,这绝对是矫枉过正。

更新:

看起来全局变量的并发初始化是可能的 - 参见 n2660 paper (第二种情况)

更新:

我已经使用 singleton_registry 实现了单例。这个想法是声明 using SomeSingleton = singleton<SomeClass>;在 singleton_registry 中注册 SomeClass 以进一步初始化,真正的单例初始化(具有所有相互依赖性)发生在 main 函数的开头(在我启动任何其他线程之前)由 singleton_registry(在堆栈上创建)。在这种情况下,我不需要使用 DLCP。它还允许我准备应用程序配置并将其统一分发给所有单例。另一个重要的用例是在 TDD 中使用单例。通常在单元测试中使用单例是一件痛苦的事情,但使用 singleton_registry 我可以为每个测试用例重新创建应用程序全局对象。

事实上,这只是一个想法的发展,即所有的单例都必须在函数 main 的开头进行初始化。通常这意味着单例用户必须编写自定义初始化函数来处理所有依赖项并准备适当的初始化参数(这是我想避免的)。

除了在单例注册期间我可能有潜在的竞争条件之外,实现看起来不错。

最佳答案

在几个项目之前,使用 vxWorks 和 C++,一位队友使用了书中的非线程安全模式(这些模式中的任何一种都是线程安全的吗?):

  • 10% 的系统启动失败。

第 1 课:如果您没有明确控制全局对象的 CTOR 的时间,它可能会因构建而异。 (而且我们找不到控制它的方法。)

第 2 课:控制 CTOR 的时间可能是第 1 课的最简单解决方案(如果它成为问题)。

根据我的经验,如果您必须拥有全局对象(而且似乎很多人不鼓励这样做),请考虑将这些全局变量限制为初始化为 0 的指针:

GlobalObject* globalobject = nullptr;

只有分配给初始化它的线程才会这样做。其他线程/任务可以旋转等待访问。

关于c++ - 可以(由编译器)使用多少线程来初始化全局对象(在函数 main 之前),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22272439/

相关文章:

java - 在 for 循环中使用相同变量名初始化多个对象时会发生什么?

c++ - Visual Studio Express 2012 项目中忽略的环境变量

c++ - 为什么没有 std::move 就不会调用 move 构造函数?

c++ - 您如何使用标准引号解释指向基类和派生类成员的指针的这种差异?

java - 内存不足错误 : unable to create new native thread using ExecutorService

c++ - 提供不确定生命周期 bool 值以在线程之间共享的最简单方法是什么?

c# - 证明int++不是原子的可靠方法

c++ - 在 C++ 中从 Linux 应用程序发送电子邮件

c# - 理解字典,使用c#向字典添加新值

c++ - 此类代码中 gcc 和 clang 之间的不同行为