Java線程中的java.util.concurrent.atomic包裏面都是類都是針對多線程下的原子變量,有包括AtomicInteger, AtomicBoolean等等多種變量的原子化實現。java
本次咱們將會解讀AtomicInteger的源碼,對變量的原子化思路進行一個理解。這也會對理解現實場景中,多線程程序原子化使用某個資源也有更好的理解。咱們抽取幾個主要的方法進行解讀。數據庫
AtomicInteger主要實現了Number接口,這個接口提供的方法都是將原子變量值轉換爲其餘類型值的接口。多線程
而主要的原子化特性則是經過持有jdk.internal.misc.Unsafe對象實現Proxy模式進行實現。函數
兩個靜態變量十分清晰:atom
Uspa
是調用了jdk.internal.misc.Unsafe對象,協助後面的原子性更新特性。
VALUE線程
則是使用了objectFieldOffset獲取了對象在JVM內存中的地址。該方法的具體實現則是一個native方法,經過C或C++對JVM內部進行操做。暫時不做細究。
private static final jdk.internal.misc.Unsafe U = jdk.internal.misc.Unsafe.getUnsafe(); private static final long VALUE = U.objectFieldOffset(AtomicInteger.class, "value"); private volatile int value;
構造函數
AtomicInteger(int)code
將傳入int值,寫入爲成員變量,令對象持有該值。
主要API及源碼解讀對象
int get()接口
比較直觀的實現,直接返回被聲明爲volatile的value。
void set(int)
比較直觀的實現,將輸入值賦值到爲volatile的value。
int getAndIncrement()
有效的邏輯,在調用Unsafe對象的下面兩個方法:
public final int getAndAddInt(Object o, long offset, int delta) { int v; do {// 循環 // getIntVolatile是一個native方法: // 之內存地址,及Object對象肯定獲取內存中的volatile值 v = getIntVolatile(o, offset); } while (!weakCompareAndSetInt(o, offset, v, v + delta)); //調用下方的weakCompareAndSetInt方法,直到更新成功則退出循環 return v; } public final boolean weakCompareAndSetInt(Object o, long offset, int expected, int x) { // 調用native方法compareAndSetInt // 以對象類型o,內存地址offset,指望值expected,輸入值x // 按照對象類型及內存地址得到期待值,對比後更新爲輸入值。 return compareAndSetInt(o, offset, expected, x); }
int getAndDecrement()
相似於getAndIncreement,調用Unsafe,對內存中數值進行操做。
經過回顧針對AtomiInteger的幾個基本方法原子化操做的解讀,咱們能夠理解爲原子操做的幾個要點:
對於數據庫記錄的原子性的解決方案,也有相似的解決方案,多線程佔用某個數據庫資源更新時,咱們也能夠先作讀取,覈對值或版本號後再做更新。
對於數據庫相關的原子性保證更新,咱們下一篇再聊聊。