【问题标题】:C++11 memory model and accessing different members of the same struct in different threadsC ++ 11内存模型和在不同线程中访问同一结构的不同成员
【发布时间】:2013-08-18 20:12:29
【问题描述】:

假设您有以下定义:

struct X
{
  char a, b;
};

X x;

现在假设您有两个线程,其中一个线程读写x.a,但从不访问x.b,而另一个线程读写x.b,但从不访问x.a。两个线程都没有使用任何锁或其他同步原语。这可以保证在 C++11 中工作吗?还是算作访问同一个对象,因此需要锁?

【问题讨论】:

  • 没关系,它们是两个不同的位置。我会留给有能力证明的人来回答。
  • @Mat 但是 C/C++ 中的每个对象/原语都必须至少有 1 个字节。而 1 个字节是“最小的可寻址单元”。
  • 我认为答案就在某处isocpp.org/blog/2013/02/…
  • @Mat 我记得在某处听说该标准要求所有字段成员具有不同的地址。虽然这是我从聊天中听到的第三手信息。我会等待有人确认/拒绝。
  • 请注意,虽然这是安全的,但它可能会导致false sharing 并降低性能。

标签: c++ multithreading c++11 thread-safety memory-model


【解决方案1】:

很安全。引用 C++11:

[intro.memory]p3:

内存位置要么是标量类型的对象,要么是所有具有非零宽度的相邻位域的最大序列。 [ 注意: 语言的各种特性,例如引用和虚函数,可能涉及程序无法访问但由实现管理的额外内存位置。 —结束说明 ] 两个执行线程 (1.10) 可以更新和访问不同的内存位置,而不会相互干扰。

[intro.memory]p5:

[ 示例: 声明为的结构

struct {
  char a;
  int b:5,
  c:11,
  :0,
  d:8;
  struct {int ee:8;} e;
}

包含四个独立的内存位置:字段a 和位字段de.ee 都是独立的内存位置,可以同时修改而不会相互干扰。位域bc 一起构成第四个内存位置。位域bc 不能同时修改,但例如ba 可以。 ——结束示例 ]

这些加在一起意味着X 的成员ab 是独立的内存位置,因此可以同时访问。

【讨论】:

  • :0 是什么,这会强制字节边界吗?
  • @WouterHuysentruit 差不多。这是一个零长度位域。引用[class.bit]p2:“作为一种特殊情况,宽度为零的未命名位域指定下一个位域在分配单元边界处对齐。”
  • 如果是unsigned int c:11 而不是int c:11 会怎样?位域的类型改变这一事实重要吗?
  • 安全。但是因为 a 和 b 在同一个缓存行中。其他线程最后一次写入时的每次读取和写入都会导致性能下降,因为它需要刷新缓存行。
猜你喜欢
  • 1970-01-01
  • 2012-05-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-11
  • 1970-01-01
  • 2020-10-10
  • 1970-01-01
相关资源
最近更新 更多