x86平台非对齐int64_t访问:并发读写线程会读取中间状态值吗?
x86架构下非对齐int64_t的线程读写行为分析
核心问题解答
1. 非对齐int64_t写入是否会触发两次内存访问?
是的。Intel x86(包括x86_64)架构硬件支持非对齐内存访问,但对于跨对齐边界的64位非对齐访问(比如你提到的地址0x7ffbc82f1c7a,低3位为0b010,意味着这个int64_t会跨越两个8字节对齐块),CPU会将单次64位读写拆分为两个独立的内存事务:分别访问两个对齐的内存块,再在内部合并数据。
2. 读取线程是否可能读到中间状态?
完全可能,这正是你遇到的情况。由于非对齐写入被拆分为两次独立操作,两次操作之间存在时间窗口:如果读取线程在第一次写入完成、第二次写入未完成时读取该变量,就会得到一个混合了旧值和新值的中间状态。
结合你的案例分析
三者的补码对比:
The two's complement of -1 is: 1111111111111111111111111111111111111111111111111111111111111111 The two's complement of 153538 is: 0000000000000000000000000000000000000000000000100101011111000010 The two's complement of -281474976557118 is: 1111111111111111000000000000000000000000000000100101011111000010
你观察到的数值变化完全符合非对齐访问的特性:
- 原数值-1的补码是全64位1
- 目标数值153538的补码是高48位为0,低16位为有效数据
- 读取到的中间值补码是高16位保留旧值的全1,低48位已更新为目标值的对应部分
这是因为你的非对齐int64_t跨越了两个8字节对齐块:第一个块的前2字节属于旧值(未被修改),而剩余的6字节以及第二个块的2字节已经被更新为目标值,读取时正好捕获到这个中间状态。
结论
这种行为在Intel x86 CPU上是完全符合预期的。需要明确:x86架构仅保证对齐的64位内存访问是原子操作(不会被拆分为多个内存事务,读写过程中不会出现中间状态);非对齐的64位访问不具备原子性,多线程场景下必然存在读到中间状态的风险。
内容的提问来源于stack exchange,提问作者world hello
相关产品推荐
相关产品推荐

