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

Java 5 線程新特性:Atomic 原子變量與線程安全陷阱

     編輯:Java 相關知識

原子變量核心價值

java.util.concurrent.atomic 提供無鎖線程安全操作:

  • 基本類型:AtomicInteger、AtomicLong、AtomicBoolean、AtomicReference
  • 數組類型:AtomicIntegerArray 等
  • 字段更新器:AtomicIntegerFieldUpdater 等
  • 累加器:LongAdder (Java 8) 高並發優於 AtomicLong

核心方法:getAndIncrement()、addAndGet(delta)、compareAndSet(expect, update) (CAS)。

錯誤案例:原子變量不等於程序線程安全

class MyRunnable implements Runnable {
    private static AtomicLong aLong = new AtomicLong(10000);
    private String name; private int x;
    MyRunnable(String name, int x) { this.name = name; this.x = x; }
    public void run() {
        System.out.println(name + "執行了" + x + ",當前余額:" + aLong.addAndGet(x));
    }
}
// 多線程運行,最終餘額可能不等於 10000 + 2000+3600+2700+600+1300+800 = 21000

多次運行結果不一,最終餘額可能 21000、15600、18300 等。原因:addAndGet 單操作原子,但 System.out.println 非原子,多線程交替導致讀取值不一致。

正確做法:原子變量 + 鎖保護業務邏輯

class MyRunnable implements Runnable {
    private static AtomicLong aLong = new AtomicLong(10000);
    private String name; private int x; private Lock lock;
    MyRunnable(String name, int x, Lock lock) { 
        this.name = name; this.x = x; this.lock = lock; 
    }
    public void run() {
        lock.lock();
        try {
            System.out.println(name + "執行了" + x + ",當前余額:" + aLong.addAndGet(x));
        } finally { lock.unlock(); }
    }
}
// 多次運行最終餘額恆為 21000

關鍵認知總結

  1. 原子變量只保證單個變量操作原子性,不保證復合邏輯原子性
  2. 業務不變量需額外同步:如轉賬需「扣款+入賬」原子,單靠 Atomic 不夠
  3. 高並發計數器:Java 8+ 首選 LongAdder,分段累加極大減少 CAS 競爭
  4. CAS 循環:compareAndSet 失敗需重試,極高爭用下性能下降

適用場景對比

場景推薦方案
簡單計數器、統計指標AtomicLong / LongAdder
單一共享對象引用更新AtomicReference
復合業務邏輯(轉賬、庫存扣減)Lock / synchronized + 原子變量
無鎖數據結構實現CAS + volatile 組合

出處:https://lavasoft.blog.51cto.com/62575/222541

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved