CAS 原理剖析

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

源码在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, %3dest, %4就是mpr表示任意寄存器,a还是eax寄存器

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

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

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




你可能感兴趣的:(Java)