为了研究Java对原子类的实现,从AtomicInteger类开始,分析Java若是对原子操做的实现。并发
原子操做是指不会被线程调度机制打断的操做;这种操做一旦开始,就一直运行到结束,中间不会有任何上下文的切换。
注:原子操做能够是一个步骤,也能够是多个操做步骤,可是其顺序不能够被打乱,也不能够被切割只执行其中的一部分。工具
首先从AtomicInteger类的属性聊起:源码分析
// setup to use Unsafe.compareAndSwapInt for updates private static final Unsafe unsafe = Unsafe.getUnsafe(); private static final long valueOffset; private volatile int value;
该类共有三个成员属性。this
再谈静态代码块(初始化)线程
try { valueOffset = unsafe.objectFieldOffset (AtomicInteger.class.getDeclaredField("value")); } catch (Exception ex) { throw new Error(ex); } }
该过程实际上就是计算成员变量value的内存偏移地址,计算后,能够更直接的对内存进行操做。
了解核心方法compareAndSet(int expect,int update):code
public final boolean compareAndSet(int expect, int update) { return unsafe.compareAndSwapInt(this, valueOffset, expect, update); }
在该方法中调用了unsafe提供的服务:对象
public final native boolean compareAndSwapInt(Object var1, long var2, int var4, int var5);
下面看看这个类在JDK中是如何实现的:内存
jboolean sun::misc::Unsafe::compareAndSwapInt (jobject obj, jlong offset,jint expect, jint update) { jint *addr = (jint *)((char *)obj + offset); //1 return compareAndSwap (addr, expect, update); } static inline bool compareAndSwap (volatile jlong *addr, jlong old, jlong new_val) { jboolean result = false; spinlock lock; //2 if ((result = (*addr == old))) //3 *addr = new_val; //4 return result; //5 }
综上所述:compareAndSet的实现依赖于两个条件:rem
了解常见操做getAndIncrement():get
return unsafe.getAndAddInt(this, valueOffset, 1); }
一样使用unsafe提供的方法:
public final int getAndAddInt(Object var1, long var2, int var4) { int var5; do { var5 = this.getIntVolatile(var1, var2);//1 } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));//2 return var5; } //getIntVolatile方法native实现 jint sun::misc::Unsafe::getIntVolatile (jobject obj, jlong offset) { volatile jint *addr = (jint *) ((char *) obj + offset); //3 jint result = *addr; //4 read_barrier (); //5 return result; //6 } inline static void read_barrier(){ __asm__ __volatile__("" : : : "memory"); }