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

Java 多線程基礎總結(六):synchronized 靜態方法與實例方法的鎖差異

     編輯:Java 相關知識

許多開發者知道 synchronized 依賴對象的隱式鎖,但對「靜態方法」與「實例方法」同步時的鎖對象差異往往存在誤區。本文通過一個經典案例徹底釐清這一核心概念。

迷思案例

public class ImplicitLock {
    public static synchronized void method1() {
        System.out.println("method1 executing...");
        try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
    }

    public synchronized void method2() {
        System.out.println("method2 executing...");
        try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }
    }
}

public class ImplicitLockSample {
    public static void main(String[] args) {
        final ImplicitLock sample = new ImplicitLock();
        new Thread(() -> sample.method1()).start(); // 呼叫靜態方法
        new Thread(() -> sample.method2()).start(); // 呼叫實例方法
    }
}

執行現象

兩個線程幾乎**同時**打印輸出,**沒有** 3 秒的等待間隔。原因在於它們持有的是**兩把完全不同的鎖**:

  • method1() 是 static,鎖對象是 ImplicitLock.class(Class 對象)。
  • method2() 是實例方法,鎖對象是 sample 這個實例(this)。

核心原理解析

  1. Class 也是對象:Class 繼承自 Object,擁有隱式鎖。
  2. static 方法隱含持有者:靜態方法不依賴實例,隱式參數是類對象本身。
  3. synchronized 綁定規則:
    • 實例方法 → 鎖 this
    • 靜態方法 → 鎖 當前類.class
    • 同步代碼塊 → 鎖括號內指定的對象
  4. sleep 不釋放鎖:Thread.sleep() 僅讓出 CPU,不釋放已持有的監視器鎖。

驗證思路

若將 method1() 改為 ImplicitLock.method1() 顯式調用,或給 method2() 加上 static,兩者將競爭同一把鎖,此時第二個線程會阻塞約 3 秒。

啟發與總結

這個例子源於對「懶漢式單例」中 static synchronized 的重新審視。許多時候我們「誤打誤撞」寫出線程安全代碼,卻不理解底層鎖機制。**搞清楚鎖到底鎖住了誰,是並發編程的基石。**

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