C ++ 11内存模型是否可以防止内存崩溃和冲突?

时间:2012-06-05 12:13:12

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

阅读C ++ 11草案我对第1.7.3条感兴趣:

  

存储器位置是标量类型的对象或者具有非零宽度的相邻位域的最大序列。 ......两个执行线程(1.10)可以更新和访问不同的内存位置,而不会相互干扰。

此条款是否可以防止与硬件相关的竞争条件,例如:

  • 未对齐的数据访问,其中内存在两个总线事务中更新(内存撕裂)?
  • 您在系统内存单元中有不同的对象,例如32位字中的两个16位有符号整数,并且每个独立对象的独立更新都需要写入整个存储单元(内存冲突)?

2 个答案:

答案 0 :(得分:5)

关于第二点,标准保证那里没有比赛。话虽如此,有人告诉我,这种保证并没有在当前的编译器中实现,甚至可能无法在某些架构中实现。

关于第一点,如果第二点得到保证,并且如果你的程序不包含任何竞争条件,那么自然结果是这也不是竞争条件。也就是说,前提是标准保证写入不同的子字位置是安全的,那么唯一可以有竞争条件的情况是多个线程访问同一个变量(即分裂)跨越单词,或者更多可能是因为这对于缓存行而言是有问题的)。

同样,这可能很难甚至无法实施。如果未对齐的数据通过缓存行,则几乎不可能保证代码的正确性而不会给性能带来巨大的成本。你应该尽量避免使用未对齐的变量以及其他原因(包括原始性能,对触及两个缓存行的对象的写入涉及将多达32个字节写入内存,以及任何其他线程是否触及任何缓存行,它还涉及缓存同步的成本......

答案 1 :(得分:1)

它不能防止内存撕裂,只有当两个线程访问相同的内存位置时才能看到(但该子句仅适用于不同的内存位置)。

根据你的例子,它似乎可以防止内存冲突。实现这一目标的最可能的方法是,一次写入少于32位的系统将具有32位char,然后两个独立的对象永远不能共享“系统存储器单元”。 (在具有32位char的系统上,两个16位整数可以相邻的唯一方法是位域。)