C++ 编译器如何保证常量成员变量的线程安全

How c++ compiler guarantees thread safety of constant member variable?

本文关键字:变量 线程 安全 成员 常量 编译器 何保证 C++      更新时间:2023-10-16

C++ 11x 标准更改了"const"关键字的语义。现在它意味着真正的线程安全。据我了解,常量成员变量等于java最终字段。

我想在 CPU icore 7 G++ 4.7.1 上检查一下。

我编译了以下代码,如 -std=c++0x -pthread -DCONST 和没有。两个可执行文件是相同的。汇编程序版本没有*围栏说明。我希望在构造函数的末尾看到*围栏。

class Big {
public:
#ifdef CONST
  const
#endif
  long a;
  Big(long a) : a(a) {
  }
  void check()
 #ifdef CONST
  const 
 #endif
  {
    assert(a == 123L);
  }
};
int main() {
  Big b(123L);
  thread t([b] () { b.check(); });
  return 0;
}

这更像是一个一般的计算机科学问题,而不是一个代码问题,但这很好,甚至很有趣。

让我们确定一些观点,如果您对这些观点或我随后的推理有任何疑问,请告诉我。 为了清楚起见,我使用"观察"一词来表示"阅读",并修改为表示"写入"。 这不是一个正式的证明。

    只要没有线程同时
  1. 修改该对象,任意数量的线程都可以同时观察某个对象而不会引起争用条件。

  2. const对象在初始化期间被修改,并且在该对象的生命周期内不会其他方式修改(我想除了销毁)。

  3. 初始化在对象的生命周期中只在一个线程中发生一次,然后才能以其他方式修改观察该对象(从技术上讲,您可以访问未初始化的对象,但是如果您设法完成它,则无论线程安全性如何,很多东西都会被破坏)。

#

2 和 #3 保证不能同时修改和观察 const 成员,这是规则 #1 的线程安全。

现在。。。 mutable会改变事情,一旦你开始创建mutable成员,类编写者就有责任确保使用mutable成员的const方法以线程安全的方式处理。

因此,编译器不保证线程安全...但逻辑确实保证了线程安全。 只要const对象,它的所有mutable成员都以线程安全的方式处理,并且该对象的所有const成员都遵守这些规则,就可以保证线程安全。

据我了解,C++11 的变化是,std::对象以前不能保证运行良好的线程安全 const 成员,我们现在有了这种保证。

视频 Herb Sutter - 你不知道 [空白] 和 [空白] 据我所知,C++11 保证 const == 线程安全的说法的来源,并很好地解释了该声明。

它不是一个直接的同义词。例如,假设你有一个 const 指针:这意味着地址本身是常量,但不一定是它的内容。因此,当由多个线程执行时,任何会修改此变量内容的函数都不被认为是线程安全的。