首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

java.util.concurrent.atomic 包源碼深度解析(二)

     編輯:Java 相關知識

續《java.util.concurrent 包結構概覽》,本文深入剖析 atomic 包核心實現:CAS 原理、Unsafe 基石、四大基本類型、數組原子類、FieldUpdater、帶標記引用等進階組件。

核心基石:CAS 與 Unsafe

CAS(Compare-And-Swap)

無鎖並發原語,三元操作:(V, A, B) → 如果 V==A 則 V=B 返回 true,否則返回 false。

  • 硬件指令級原子性(CPU LOCK CMPXCHG)
  • 避免線程阻塞/上下文切換,吞吐量高
  • ABA 問題:需配合版本戳/標記解決(見 AtomicStampedReference)

sun.misc.Unsafe

JVM 內部類,提供「越過 Java 安全檢查」的底層能力:

  • 直接內存分配/釋放(allocateMemory/freeMemory)
  • 對象字段偏移量計算(objectFieldOffset)
  • CAS 操作入口(compareAndSwapInt/Long/Object)
  • 內存屏障(loadFence/storeFence/fullFence)

所有 atomic 類最終委託 Unsafe 實現原子操作。

四大基本原子類

類底層類型核心字段適用場景
AtomicIntegerintvolatile int value計數器、序列號、狀態標記
AtomicLonglongvolatile long value高併發 ID 生成、時間戳、統計聚合
AtomicBooleanint (0/1)volatile int value開關標誌、一次性初始化鎖
AtomicReference<V>Objectvolatile V value無鎖單例、引用交換、不可變對象更新

統一 API 模式


// 獲取/設置
get() / set(newValue)

// CAS 更新
compareAndSet(expect, update)        // 強一致性
weakCompareAndSet(expect, update)    // 弱一致性,允許虛假失敗(性能優)

// 無條件設置(有序性語義)
lazySet(newValue)                    // 釋放語義,不保證立即可見

// 獲取並更新(原子複合操作)
getAndSet(newValue)
getAndIncrement() / incrementAndGet()
getAndAdd(delta) / addAndGet(delta)

原子數組類

  • AtomicIntegerArray、AtomicLongArray、AtomicReferenceArray
  • 無 AtomicBooleanArray(可用 IntegerArray 代替)
  • 數組元素獨立原子更新,volatile 修飾數組引用無意義,需 Unsafe 逐元素操作
  • API 增加 index 參數:getAndIncrement(int i)

FieldUpdater:反射式字段原子更新


// 靜態工廠獲取 Updater
AtomicIntegerFieldUpdater updater = 
    AtomicIntegerFieldUpdater.newUpdater(User.class, "age");

// 目標字段要求:
// 1. volatile 修飾
// 2. 類型匹配(Integer/Long/Object)
// 3. 非 static

// 使用
updater.getAndIncrement(user);  // 原子更新 user.age

門面模式:抽象類 + 私有實現類,newUpdater() 返回具體實例。

帶標記/版本的引用:解決 ABA

類Pair 結構用途
AtomicMarkableReference<V><V, Boolean>邏輯刪除標記、狀態翻轉
AtomicStampedReference<V><V, Integer>版本號、修訂計數、ABA 完全解決

內部封裝 AtomicReference<Pair>,CAS 同時比較引用與標記/版本。

關鍵源碼洞察

  • AtomicLong.set() 非原子?實則視 JVM 是否支援 VM_SUPPORTS_LONG_CAS,不支援則退化為鎖
  • weakCompareAndSet 可能虛假失敗,適用於計數器統計等容忟偶發重試場景
  • lazySet 利用 Unsafe.putOrderedLong 實現釋放語義,比 volatile write 輕量
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved