阅读 C++11 的草稿,我对第 1.7.3 节感兴趣:
内存位置要么是标量类型的对象,要么是所有具有非零宽度的相邻位域的最大序列。... 两个执行线程 (1.10) 可以更新和访问单独的内存位置,而不会相互干扰。
此条款是否保护与硬件相关的竞争条件,例如:
- 在两个总线事务中更新内存的未对齐数据访问(内存撕裂)?
- 在系统内存单元中有不同的对象,例如 32 位字中有两个 16 位有符号整数,并且单独对象的每次独立更新都需要写入整个内存单元(内存冲突)?
阅读 C++11 的草稿,我对第 1.7.3 节感兴趣:
内存位置要么是标量类型的对象,要么是所有具有非零宽度的相邻位域的最大序列。... 两个执行线程 (1.10) 可以更新和访问单独的内存位置,而不会相互干扰。
此条款是否保护与硬件相关的竞争条件,例如:
关于第二点,标准保证那里不会有比赛。话虽如此,我被告知当前的编译器没有实现这个保证,在某些架构中甚至可能无法实现。
关于第一点,如果第二点得到保证,并且如果您的程序不包含任何竞态条件,那么自然的结果就是这也不会是竞态条件。也就是说,假设标准保证写入不同的子字位置是安全的,那么唯一可能出现竞争条件的情况是多个线程访问同一个变量(即跨字拆分,或者更可能是这是有问题的,跨缓存行)。
同样,这可能很难甚至不可能实现。如果您的未对齐数据跨越缓存行,那么几乎不可能保证代码的正确性而不会对性能造成巨大成本。由于这个原因和其他原因(包括原始性能,对涉及两个缓存行的对象的写入涉及将多达 32 个字节写入内存,并且如果任何其他线程正在触及任何一个缓存行,它还涉及缓存同步的成本......
它不能防止内存撕裂,这仅在两个线程访问同一内存位置时可见(但该子句仅适用于单独的内存位置)。
根据您的示例,它似乎可以防止内存冲突。实现这一点的最有可能的方法是,一个不能一次写入少于 32 位的系统将具有 32-bit char
,然后两个单独的对象永远不能共享一个“系统内存单元”。(在具有 32 位的系统上,两个 16 位整数可以相邻的唯一方法char
是作为位域。)