爲了研究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"); }