如何以原子方式读取x86 ASM中的值?

时间:2010-07-28 04:06:18

标签: assembly x86 thread-safety atomic

我知道如何在x86 ASM中自动写入值。但我怎么读一个? LOCK前缀不能与mov。

一起使用

为了增加价值,我正在做:

lock inc dword ptr Counter

如何以线程安全的方式读取计数器?

4 个答案:

答案 0 :(得分:5)

我在this帖子中向您解释:

  

访问可缓存的内存   分割总线宽度,缓存线,   和页面边界不保证   英特尔酷睿2双核处理器,   Intel Core Duo,Pentium M,Pentium 4,   Intel Xeon,P6系列,Pentium和   Intel486处理器。英特尔酷睿2   Duo,Intel Core Duo,Pentium M,   Pentium 4,Intel Xeon和P6系列   处理器提供总线控制信号   允许外部存储器子系统   使拆分访问成为原子;   但是,非对齐数据访问将会   严重影响了业绩   处理器,应该避免。

所以使用:

LOCK        CMPXCHG   EAX, [J]

LOCK CMPXCHG第一个围栏缓存内存,并将EAX与目标值进行比较,如果目标值不相等则则EAX中的结果为目标值。

编辑: 链接到:

Intel® 64 and IA-32 Architectures Software Developer’s Manuals

Volume 3A: System Programming Guide检查第8.1.1节

同时检查:Optimization Reference Manual section: CHAPTER 7 OPTIMIZING CACHE USAGE

答案 1 :(得分:4)

我不是汇编专家,但字大小(在x86,32位上)读/写应该是原子的。

你需要锁定增量的原因是因为它既是读也是写。

答案 2 :(得分:1)

对于简单的阅读,它主要是关于对齐。确保原子读取的最简单方法是始终使用“自然”对齐 - 即,对齐至少与项目的大小一样大(例如,32位项目是32位对齐)。

未对齐的读取不一定是原子的。举一个极端的例子,考虑在奇数地址读取32位值,其中第一个字节在一个高速缓存行中,其他三个字节在另一个高速缓存行中。在这种情况下,原子读取基本上是不可能的。

由于(至少大多数)处理器使用64位宽的内存总线,因此希望以原子方式读取的最大项是64位。

答案 3 :(得分:1)

阅读其他回复很有意思。我认为@GJ可能就是钱。

多年来,32位读写始终是原子的。只是在最近几年才真正积极的缓存,这已不再保证。

我想这就是为什么我更喜欢C ++,Java或者我和机器代码之间的一些东西。这些天机器代码太复杂而无法可靠地编写(除非你 很多 以保持你的技能敏锐)。幸运的是,今天的优化编译器非常好,您很少需要手动优化的汇编程序的性能。