CAS 原理剖析

xiaoxiao2021-02-28  31

此文主要借鉴 点击打开链接

源码在atomic_linux_x86.inline.hpp中

openjdk-8u40-src-b25-10_feb_2015\openjdk\hotspot\src\os_cpu\linux_x86\vm\atomic_linux_x86.inline.hpp

inline jint Atomic::cmpxchg (jint exchange_value, volatile jint* dest, jint compare_value) { int mp = os::is_MP(); __asm__ volatile (LOCK_IF_MP(%4) "cmpxchgl %1,(%3)" : "=a" (exchange_value) : "r" (exchange_value), "a" (compare_value), "r" (dest), "r" (mp) : "cc", "memory"); return exchange_value; }

这是一段小汇编,__asm__说明是ASM汇编,__volatile__禁止编译器优化

os::is_MP判断当前系统是否为多核系统,如果是就给总线加锁,所以同一芯片上的其他处理器就暂时不能通过总线访问内存,保证了该指令在多处理器环境下的原子性。

在正式解读这段汇编前,我们来了解下嵌入汇编的基本格式:

asm ( assembler template : output operands /* optional */ : input operands /* optional */ : list of clobbered registers /* optional */ );

template就是cmpxchgl %1,(%3)表示汇编模板

output operands表示输出操作数,=a对应eax寄存器

input operand 表示输入参数,%1 就是exchange_value, %3是dest, %4就是mp, r表示任意寄存器,a还是eax寄存器

list of clobbered registers就是些额外参数,cc表示编译器cmpxchgl的执行将影响到标志寄存器, memory告诉编译器要重新从内存中读取变量的最新值,这点实现了volatile的感觉。

那么表达式其实就是cmpxchgl exchange_value ,dest,我们会发现%2也就是compare_value没有用上,这里就要分析cmpxchgl的语义了。cmpxchgl末尾l表示操作数长度为4,上面已经知道了。cmpxchgl会默认比较eax寄存器的值即compare_value和exchange_value的值,如果相等,就把dest的值赋值给exchange_value,否则,将exchange_value赋值给eax。具体汇编指令可以查看Intel手册CMPXCHG

最终,JDK通过CPU的cmpxchgl指令的支持,实现AtomicInteger的CAS操作的原子性。

转载请注明原文地址: https://www.6miu.com/read-2623379.html

最新回复(0)