And*_*zel 10
根据官方 ISO C 标准的 §5.1.2.4 ¶25 和 ¶4,两个不同的线程使用非原子操作以无序方式写入同一内存位置会导致未定义行为。如果所有线程都写入相同的值,则 ISO C 标准也不例外。
尽管 x86/x64 CPU 的 Intel/AMD 规范保证将 32 位整数写入 4 字节对齐的地址是原子的,但 ISO C 标准不保证这样的操作是原子的,除非您使用由 ISO C 标准保证为原子的数据类型(例如atomic_int_least32_t)。因此,即使您的线程将 type 值写入int32_t4 字节对齐的地址,根据 ISO C 标准,您的程序仍然会导致未定义的行为。
然而,出于实际目的,假设编译器正在生成以原子方式执行操作的汇编指令可能是安全的,前提是满足对齐要求。
即使内存写入未对齐并且 CPU 不会以原子方式执行写入指令,您的程序仍可能按预期工作。将一个写操作拆分为两个写操作应该无关紧要,因为所有线程都在写入完全相同的值。
如果您决定不使用原子变量,那么您至少应该将该变量声明为volatile. 否则,编译器可能会发出汇编指令,导致变量仅存储在 CPU 寄存器中,因此其他 CPU 可能永远不会看到对该变量的任何更改。
因此,要回答您的问题:可能没有必要将您的变量声明为原子变量。但是,它仍然强烈推荐。通常,对多个线程访问的变量的所有操作都应该是原子的或受互斥锁保护。此规则的唯一例外是所有线程都对该变量执行只读操作。
玩弄未定义的行为可能很危险,通常不推荐。特别是,如果编译器检测到导致未定义行为的代码,则允许将该代码视为无法访问并对其进行优化。在某些情况下,一些编译器实际上会这样做。有关详细信息,请参阅Microsoft 博主 Raymond Chen 撰写的这篇非常有趣的帖子。
此外,请注意写入同一位置(甚至同一缓存线)的多个线程可能会中断CPU 管道,因为 x86/x64 架构保证了必须强制执行的强内存排序。如果 CPU 的高速缓存一致性协议检测到由于另一个 CPU 写入同一高速缓存行而可能违反了内存顺序,则可能必须清除整个 CPU 管道。出于这个原因,所有线程写入不同的内存位置(在不同的缓存行中,至少相隔 64 字节)并在所有线程同步后分析写入的数据可能更有效。
| 归档时间: |
|
| 查看次数: |
386 次 |
| 最近记录: |