对单个核心 CPU 上的变量的写入是原子的吗?

Is a write to variable on a single core CPU atomic?

我有一个带两个线程的单核 CPU(ARM Cortex M3,32 位)。假设以下情况:

// Thread 1:
int16_t a = 1;
double b = 1.0;
// Do some other fancy stuff including starting Thread 2
for (;;) {std::cout << a << "," <<b;}

// Thread 2:
a = 2;
b = 2.0;

我可以处理以下输出:

如果不使用 mutex 或其他锁定机制,我能否确定输出始终是其中之一 (1/2)?更具体地说,这个编译器是否依赖? int16double 的行为是否不同?

; 之前操作的评估顺序不能保证从左到右,即使是,它们也不是原子的,如果您尝试同时读取和写入 a ,您将遇到段错误(它们可以并且确实需要多个周期来执行并且上下文切换可以打断它)。

特别是在 arm 上,读取和写入在 cpu 上的队列中进行,在那里它们可以自由重新排序(过去的内存障碍除外),即使在 cpu 上不重新排序内存编译器也可以自由地重新排序它们。没有什么可以阻止您的作业和阅读向前或向后移动,因此您无法保证任何值或顺序的状态。

这主要取决于 CPU,虽然理论上任何涉及 C11 之前的多线程的事情充其量都是实现定义的,最坏的情况是未定义的行为,因此编译器可能会做任何事情。

如果你可以忽略做傻事的疯狂编译器,并假设编译器将以合理的方式使用 CPU 的设施,这主要取决于 CPU 支持什么。

Cortex-M3 是 32 位 CPU,具有 32 位总线且没有 FPU。因此,读取和写入 32 位及更小的值通常是原子的。然而,double 是 64 位,因此双精度的任何 read/write 都将涉及两条指令并且是非原子的。因此,如果一个线程读取而另一个线程写入,您可能会从一个值中获得一半,而从另一个中获得一半。

现在在您的具体示例中,值 1.0 和 2.0 的下半部分均为 0,因此 'mix' 是无害的,但其他值不会有这种行为。