x64:并发写入布尔数组

Kev*_*ier 2 c memory 64-bit x86 volatile

假设我在 C 中有一个这样的数组:

static volatile bool my_array[128] = {0};
Run Code Online (Sandbox Code Playgroud)

最重要的是,我有 128 个线程,每个线程在完成时都会写入不同的索引。true

这会产生一些问题吗?在 x64 上写入单个字节不会影响周围的字节,对吗?

我只是问,因为我不确定CPU/内存控制器/等是否总是读取8(或4)字节,然后写入它们。这会产生一些奇怪的竞争条件。

多谢

Ian*_*ott 6

根据 C 标准的定义,数组的两个元素不会存储在同一内存位置,因此数组的单独元素的并发访问或修改不会相互干扰,正如 C17 3.14 第 2 段所确认的那样:

3.14

  1. 记忆位置

    标量类型的对象,或全部具有非零宽度的相邻位字段的最大序列

  2. 注 1:两个执行线程可以更新和访问单独的内存位置,而不会相互干扰。

唯一需要注意的是,所有具有非零宽度的相邻位域序列中不同位域成员的并发更新,如 C17 3.14 的下一段所证实:

  1. 注 2:位字段和相邻的非位字段成员位于不同的内存位置。这同样适用于两个位字段,如果一个位字段在嵌套结构声明内声明而另一个未声明,或者如果两者由零长度位字段声明分隔,或者如果它们由非位分隔- 现场成员声明。如果在同一结构中声明的所有成员也是(非零长度)位字段,则同时更新同一结构中的两个非原子位字段是不安全的,无论这些中间位字段的大小是什么。

(强调我的)。

C17 3.14 的下一段提供了一个示例:

  1. 示例结构体声明为

    struct {
          char a;
          int b:5, c:11,:0, d:8;
          struct { int ee:8; } e;
    }
    
    Run Code Online (Sandbox Code Playgroud)

    包含四个独立的内存位置:成员a、位字段de.ee都是独立的内存位置,并且可以同时修改而不会相互干扰。位字段bc一起构成第四个存储位置。位字段bc不能同时修改,但ba等可以同时修改。


笔记

我推测,在某些体系结构上,并发访问“打包”数组的不同元素或打包结构的不同成员可能是不安全的,但这超出了 C 规范的范围。

  • 是的,C++ `std::vector<bool>` 密集地打包位,这使得从单独的线程写入单独的索引变得不安全。(迭代器不仅仅是指针;它很混乱,而且[对于一个好的数据结构来说,这是一个糟糕/令人惊讶的名字](https://isocpp.org/blog/2012/11/on-vectorbool)。) (2认同)