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