我刚刚阅读了this有关当前boost::mutex
实施背后的实际原因的文章,并注意到以下短语:
块范围静态还存在潜在竞争的额外问题 条件在"第一次通过",这可能导致 析构函数在流行的编译器上运行多次,这是 未定义的行为 - 编译器通常使用等效的调用 atexit以确保反向完成销毁 构造的顺序,以及可能导致的初始化竞赛 要运行两次的构造函数也可能导致析构函数 注册了两次
这是真的吗?我是否真的应该通过原子操作或类似的东西检查此对象的另一个线程是否已经在析构函数中?即使在C ++ 11 - C ++ 14中,我应该这样做吗?因为据我所知,对于具有静态存储持续时间的同一本地对象,不能再有多个"构造函数可以同时从多个线程调用#34;自C ++ 11以来的问题 - 它要求另一个线程应该等待构造函数的完成。我是对的吗?
答案 0 :(得分:2)
看起来这篇文章是在C ++ 11之前编写的,其中包括:
[...]下一版C ++标准,计划于2009年发布。[...]
这就是C ++ 11之前的情况,由于线程不是C ++ 11之前的内存模型的一部分,因此没有说明在这种情况下发生了什么。
这在C ++ 11和draft C++11 standard部分6.7
声明声明中发生了变化(强调我的):
所有带有静态的块范围变量的零初始化(8.5) 存储持续时间(3.7.1)或线程存储持续时间(3.7.2)是 在任何其他初始化发生之前执行。 [...] 除此以外 在控件第一次通过时初始化这样的变量 它的声明;这样的变量被认为是初始化的 完成初始化。如果初始化退出 抛出异常,初始化不完整,所以会 下次控制进入声明时再试一次。 如果 控件在变量的同时输入声明 在初始化时,并发执行应等待完成 初始化。 [...]
Pre C ++ 11我们必须像处理任何其他关键部分一样处理静态局部变量。我们可以在帖子C++ scoped static initialization is not thread-safe, on purpose!中找到对C ++ 11前的情况的精彩描述。