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

Java 線程安全核心:變量作用域、同步鎖與類級鎖實戰

     編輯:Java 相關知識

線程不安全的根源

Java 多線程環境下,線程安全問題僅源於共享可變狀態:

  • 類變量(static):存儲在方法區,全局共享。
  • 實例變量(非 static):存儲在堆,多線程訪問同一對象時共享。
  • 局部變量:存儲在線程私有棧中,天然線程安全,無需同步。

實戰演示:計數器不安全


public class Test implements Runnable {
    private int j;  // 實例變量,共享狀態

    public void testThreadLocal() {
        System.out.println(Thread.currentThread().getId() + ":============================= begin");
        j = 2;
        System.out.println(Thread.currentThread().getId() + ":" + j);
        j = 20;
        System.out.println(":" + j * 3 + ":");  // 預期 60
        System.out.println(Thread.currentThread().getId() + ":============================= end");
    }

    public static void main(String[] args) {
        Test t = new Test();
        for (int i = 0; i < 3000; i++) {
            new Thread(t).start();  // 共享同一 Test 實例
        }
    }
    @Override public void run() { testThreadLocal(); }
}

現象:輸出出現 :6: 等錯誤值(預期 :60:),證明多線程交織修改 j 導致數據競爭。

同步關鍵字的兩種鎖定目標

錯誤嘗試:多實例 + 實例鎖


// main 中 new Thread(new Test()).start() 創建多個實例
public synchronized void testThreadLocal() { ... }  // 鎖 this

無效:每個線程鎖的是不同的 this,互不阻塞。

正確方案一:單實例 + 實例鎖


// main 中共享同一 Test 實例
public synchronized void testThreadLocal() { ... }  // 鎖同一 this,有效

正確方案二:多實例 + 類鎖(Class 鎖)


public void testThreadLocal() {
    synchronized (this.getClass()) {  // 或 synchronized (Test.class)
        // 臨界區代碼
    }
}

原理:Test.class 是 JVM 加載類時創建的唯一 Class 對象,全局唯一,所有實例共享此鎖。

靜態變量場景:static synchronized


private static int j;  // 類變量

public synchronized static void testThreadLocal() { ... }
// 等價於
public static void testThreadLocal() {
    synchronized (Test.class) { ... }
}

靜態方法無 this,synchronized 直接鎖 Class 對象,天然適配類變量保護。

進階:long/double 非原子性

JVM 規範允許 64 位 long/double 非原子寫入(分兩次 32 位操作)。多線程並發寫入可能導致「撕裂讀/寫」(高低 32 位來自不同線程)。

  • 解決:加 volatile 或用 AtomicLong/AtomicReference,或同步塊保護。

最佳實踐總結

總結

線程安全的核心是識別共享可變狀態,然後選擇正確的鎖粒度(對象鎖 vs 類鎖)或無鎖工具。記住:synchronized(this) 只保護同一實例;跨實例保護共享邏輯/靜態數據,必須升級為 synchronized(MyClass.class)。這是 Java 併發編程從入門到精通的分水嶺。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
場景推薦鎖策略
保護實例變量,單實例共享synchronized 實例方法 / synchronized(this)
保護實例變量,多實例並發synchronized(ClassName.class) 類鎖
保護類變量 (static)synchronized static 方法 / synchronized(ClassName.class)
高併發、細粒度控制ReentrantLock / ReadWriteLock / StampedLock
簡單計數/狀態AtomicInteger / LongAdder / ThreadLocal