此文主要借鉴 点击打开链接
源码在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操作的原子性。
