AtomicInteger
和 volatile Integer
雖然都與線程安全有關,但本質完全不同。它們的主要區別體現在原子性保證和功能上:
🔍 核心區別對比表
特性 | volatile Integer | AtomicInteger |
---|---|---|
原子性 | ? 不保證復合操作原子性 | ? 保證所有操作的原子性 |
自增操作安全性 | ? i++ 不安全 | ? incrementAndGet() 安全 |
CAS 操作 | ? 不支持 | ? 原生支持 compareAndSet() |
函數式更新 | ? 不支持 | ? 支持 updateAndGet() |
性能表現 | 簡單讀寫快 | 復合操作遠優于鎖同步 |
內部原理 | 內存屏障 + 禁止重排序 | volatile + CAS 自旋 |
?? volatile Integer 的問題演示
public class VolatileCounter {private volatile Integer count = 0;// 線程不安全的操作!public void increment() {count++; // 實際分為三步: 讀 -> 改 -> 寫}public int getCount() {return count;}
}
問題代碼解釋:
- 當線程A讀取
count=0
- 線程B同時讀取
count=0
- 線程A計算
0+1=1
寫入 - 線程B計算
0+1=1
寫入 - 結果:實際執行了兩次自增,值卻只變為1
? AtomicInteger 解決方案
import java.util.concurrent.atomic.AtomicInteger;public class SafeCounter {private final AtomicInteger count = new AtomicInteger(0);// 線程安全操作public void safeIncrement() {count.incrementAndGet(); // 原子操作}public int getCount() {return count.get();}
}
關鍵原理:
// AtomicInteger 內部實現原理
public final int incrementAndGet() {return U.getAndAddInt(this, VALUE, 1) + 1;
}// 實際執行(Unsafe類):
public final int getAndAddInt(Object o, long offset, int delta) {int v;do {v = getIntVolatile(o, offset); // 1. 讀取volatile值} while (!weakCompareAndSetInt(v, v + delta)); // 2. CAS自旋return v;
}
📌 本質區別總結
-
volatile 的作用
- 只保證可見性和有序性
- 寫操作立即刷新到主存
- 讀操作總是獲取最新值
-
AtomicInteger 的優勢
- 通過 volatile 變量 + CAS 自旋實現復合操作原子性
- 內置支持數學運算、比較交換等功能
- 封裝了線程安全的無鎖算法
-
性能對比場景
// 測試代碼片段 for(int i=0; i<1000000; i++) {// volatile版:1000ms+ // AtomicInteger版:200ms }
🔄 關系示意圖
volatile int value (基本保障)│▼+-----------------+| AtomicInteger |→ CAS保證復合操作原子性| (封裝增強) |→ 提供原子操作方法族+-----------------+
可見
AtomicInteger
內部使用 volatile 保證可見性(通過private volatile int value
字段),但增加了 CAS 機制來實現更復雜的原子操作,這是單純 volatile 做不到的。
💡 使用建議
- 需要單一基本類型的原子操作 → 用
AtomicInteger/Long/Boolean
- 需要簡單可見性保證 → 用
volatile
- 需要對象引用的原子更新 → 用
AtomicReference
- JDK8+高并發計數場景 → 用
LongAdder