CAS(Compare And Swap) 比较与交换:这是一个不断循环的过程,一直到变量值修改成功为止。CAS本身是有硬件指令来提供支持的,换句话说,硬件是通过一个原子指令来实现比较与交换的;因此,CAS可以确保变量操作的原子性的。 在IA64,x86 指令集中有 cmpxchg 指令完成 CAS 功能,在 sparc-TSO 也有 casa 指令实现,而在 ARM 和 PowerPC 架构下,则需要使用一对 ldrex/strex 指令来完成 LL/SC 的功能。在精简指令集的体系架构中,则通常是靠一对儿指令,如:load and reserve 和 store conditional 实现的,在大多数处理器上 CAS 都是个非常轻量级的操作,这也是其优势所在。
public class MyTest2 { public static void main(String[] args) { AtomicInteger atomicInteger = new AtomicInteger(5); System.out.println(atomicInteger.get()); System.out.println(atomicInteger.getAndSet(8)); System.out.println(atomicInteger.get()); System.out.println(atomicInteger.getAndIncrement()); System.out.println(atomicInteger.get()); } }
输出: 5 5 8 8 9
AtomicInteger实现
1 2 3 4 5 6 7 8 9 10 11 12 13
public class AtomicInteger extends Number implements java.io.Serializable { // Unsafe非开源的,只能在jkd内部调用 private static final Unsafe unsafe = Unsafe.getUnsafe(); //值在对象里边的内存偏移量,即 value在AtomicInteger对象里边的内存偏移量。 private static final long valueOffset; //AtomicInteger包装的数值,比如实例包装的是数字5,volatile为了保证可见性 private volatile int value;
public final int getAndSet(int newValue) { //this是AtomicInteger对象,valueOffset是偏移量,将要写入的值是newValue return unsafe.getAndSetInt(this, valueOffset, newValue); } }
unsafe的getAndAddLong:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
public final long getAndAddLong(Object var1, long var2, long var4) { long var6; //循环重试【循环开销问题】 do { var6 = this.getLongVolatile(var1, var2); } while(!this.compareAndSwapLong(var1, var2, var6, var6 + var4)); return var6; } //var1:我们号操作的对象,AtomicInteger对象,在C++里边就是AtomicInteger的内存位置 //var2:要操作的变量在AtomicInteger里边内存便宜位置,即valueOffset。 //var6:变量的预期的值 //var6 + var4:将要写入的新的值 // 此方法是通过一个cpu指令来完成的,是可以保证原子性。 this.compareAndSwapLong(var1, var2, var6, var6 + var4)
Unsafe
1 2 3 4 5 6 7 8 9 10 11 12 13 14
//构造器是私有的,不能通过new得到对象 private Unsafe() { } public static Unsafe getUnsafe() { //获取调用此getUnsafe方法的对象的Class对象 Class var0 = Reflection.getCallerClass(); //调用者类的类加载器不是启动类加载器,则抛出异常 if (!VM.isSystemDomainLoader(var0.getClassLoader())) { throw new SecurityException("Unsafe"); } else { //正常返回 return theUnsafe; } }