前言
今天看到一篇文章里面提到,16bit/32bit的写可以保证原子性。自己对这个知识点不理解,所以上网找些资料进行总结。
正文
所谓原子操作,就是“不可中断的一个或一系列操作”。在多线程程序中,原子操作是一个非常重要的概念,它常常用来实现一些同步机制,同时也是一些常见的多线程Bug的源头。
例如:x++,在不同编译系统中会按多条指令的形式来处理这种语句。从内存中读x的值到寄存器中,对寄存器加1,再把新值写回x所处的内存地址
但今天要讨论的是每条指令是否可以认为是原子操作。
要彻底理解这个问题,我们首先需要从硬件讲起。以常见的X86 CPU来说,根据Intel的参考手册,它基于以下三种机制保证了多核中加锁的[原子操作:
(1)Guaranteed atomic operations (注:8.1.1节有详细介绍)
(2)Bus locking, using the LOCK# signal and the LOCK instruction prefix
(3)Cache coherency protocols that ensure that atomic operations can be carried out on cached data structures (cache lock); this mechanism is present in the Pentium 4, Intel Xeon, and P6 family processors
这三个机制相互独立,相辅相承。简单的理解起来就是
(1)一些基本的内存读写操作是本身已经被硬件提供了原子性保证(例如读写单个字节的操作);
(2)一些需要保证原子性但是没有被第(1)条机制提供支持的操作(例如read-modify-write)可以通过使用”LOCK#”来锁定总线,从而保证操作的原子性
(3)因为很多内存数据是已经存放在L1/L2 cache中了,对这些数据的原子操作只需要与本地的cache打交道,而不需要与总线打交道,所以CPU就提供了cache coherency机制来保证其它的那些也cache了这些数据的processor能读到最新的值
CPU对原子操作的影响
那么CPU对哪些(1)中的基本的操作提供了原子性支持呢?根据Intel手册8.1.1节的介绍:
从Intel486 processor开始,以下的基本内存操作是原子的:
读写一个byte Reading or writing a word aligned on a 16-bit boundary
读写16bit(2byte)内存对齐的字(word) Reading or writing a doubleword aligned on a 32-bit boundary
读写32bit(4byte)内存对齐的双字(dword)
从Pentium processor开始,除了之前支持的原子操作外又新增了以下原子操作:
Reading or writing a quadword aligned on a 64-bit boundary
对齐到64位边界的四字的读写
16-bit accesses to uncached memory locations that fit within a 32-bit data bus
未缓存且在32位数据总线范围之内的内存地址的访问
从P6 family processors开始,除了之前支持的原子操作又新增了以下原子操作:
P6系列处理器(以及以后生产的处理器)确保以下对基本存储器的操作行为为原子操作:
Unaligned 16-, 32-, and 64-bit accesses to cached memory that fit within a cache line
对单个cache line中缓存地址的未对齐的16/32/64位访问(非对齐的数据访问非常影响性能)
那么哪些操作是非原子的呢?
Accesses to cacheable memory that are split across bus widths, cache lines, and page boundaries are not guaranteed to be atomic by the Intel Core 2 Duo, Intel®Atom™, Intel Core Duo, Pentium M, Pentium 4, Intel Xeon, P6 family, Pentium, and Intel486 processors.(说点简单点,那些被总线带宽、cache line以及page大小给分隔开了的内存地址的访问不是原子的,你如果想保证这些操作是原子的,你就得求助于机制(2),对总线发出相应的控制信号才行)。
需要注意的是尽管从P6 family开始对一些非对齐的读写操作已经提供了原子性保障,但是非对齐访问是非常影响性能的,需要尽量避免。当然了,对于一般的程序员来说不需要太担心这个,因为大部分编译器会自动帮你完成内存对齐。
文档信息
- 本文作者:L1Chenxv
- 本文链接:https://l1chenxv.github.io//2025/05/11/Atomic-write/
- 版权声明:自由转载-非商用-非衍生-保持署名(创意共享3.0许可证)