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

Java 多線程同步核心:synchronized 代碼塊與同步方法深度對比

     編輯:Java 相關知識

問題現場:賣票系統的併發缺陷

class RunnableDemo implements Runnable {
    private int tickets = 5;
    @Override public void run() {
        for (int i = 0; i < 10; i++) {
            Thread.sleep(500);
            if (tickets > 0) System.out.println("車票: " + tickets--);
        }
    }
}
// 三線程共享同一 RunnableDemo 實例
// 輸出示例:5 4 3 2 1 2 (出現負數/重複,數據競爭)

方案一:synchronized 同步代碼塊

public void run() {
    for (int i = 0; i < 10; i++) {
        Thread.sleep(500);
        synchronized (this) { // 鎖住當前實例
            if (tickets > 0) System.out.println("車票: " + tickets--);
        }
    }
}

方案二:synchronized 同步方法

public synchronized void show() { // 隱式鎖 this
    if (tickets > 0) System.out.println("車票: " + tickets--);
}
public void run() {
    for (int i = 0; i < 10; i++) show();
}

兩者輸出一致(正確)

車票: 5
車票: 4
車票: 3
車票: 2
車票: 1

深度對比

維度同步代碼塊同步方法
鎖對象顯式指定(this、類對象、任意對象)隱式:實例方法鎖 this,靜態方法鎖 Class 對象
粒度控制精細,僅鎖關鍵區段整個方法
靈活性高,可針對不同共享資源用不同鎖低,方法級粗粒度
性能略優(鎖範圍小)略差
可讀性稍低高,語義清晰

進階:volatile 能替代嗎?

不能。volatile 僅保證可見性與有序性,不保證原子性。tickets-- 是「讀-改-寫」三步操作,volatile 無法防止競爭。需配合 AtomicInteger 或 synchronized/Lock。

參考:IBM 文檔:正確使用 Volatile 變量

最佳實踐

  1. 優先使用 java.util.concurrent 包下的線程安全集合、原子類、鎖(ReentrantLock)。
  2. 必須用 synchronized 時,盡量縮小同步塊範圍,避免在同步塊中調用耗時操作(IO、睡眠、外部服務)。
  3. 靜態共享資源用 synchronized (MyClass.class) 或 static synchronized 方法。
  4. 避免使用 String、基本類型包裝類作為鎖(常量池/自動裝箱導致鎖對象不一致)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved