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

Java 多線程同步進階:Doug Lea Mutex 實現原理與 Sync 介面設計藝術

     編輯:Java 程式設計入門

背景:為什麼需要 Mutex?

synchronized 關鍵字鎖定範圍侷限於方法/代碼塊,無法跨方法、跨對象協調。Doug Lea 的 concurrent 包引入 Sync 介面,統一鎖、閘、條件變量語義,實現面向抽象編程,靈活切換同步策略。

Sync 介面定義

public interface Sync {
    void acquire() throws InterruptedException;      // 獲取許可(阻塞)
    boolean attempt(long msecs) throws InterruptedException; // 嘗試獲取(帶超時)
    void release();                                   // 釋放許可
}
  • acquire() / attempt() 可拋 InterruptedException,需捕獲
  • release() 不拋異常,適合 finally 區塊保證釋放

標準使用模板

class X {
    private final Sync gate = new Mutex(); // 或 Semaphore 等

    public void m() {
        try {
            gate.acquire();
            try {
                // 臨界區業務邏輯
            } finally {
                gate.release(); // 保證釋放
            }
        } catch (InterruptedException ex) {
            // 中斷應對:記錄、恢復中斷狀態、拋出等
        }
    }
}

Mutex 實現原碼深度解析

public class Mutex implements Sync {
    protected boolean inuse_ = false; // 鎖狀態

    public void acquire() throws InterruptedException {
        if (Thread.interrupted()) throw new InterruptedException(); // (1) 快速失敗
        synchronized (this) {
            try {
                while (inuse_) wait(); // (2) 自旋等待
                inuse_ = true;         // 佔用鎖
            } catch (InterruptedException ex) {
                notify();              // (3) 喚醒其他等待者
                throw ex;
            }
        }
    }

    public synchronized void release() {
        inuse_ = false;
        notify(); // 喚醒一個等待者
    }

    public boolean attempt(long msecs) throws InterruptedException {
        if (Thread.interrupted()) throw new InterruptedException();
        synchronized (this) {
            if (!inuse_) {
                inuse_ = true;
                return true;
            }
            if (msecs <= 0) return false;

            long waitTime = msecs;
            long start = System.currentTimeMillis();
            try {
                for (;;) {
                    wait(waitTime);
                    if (!inuse_) {
                        inuse_ = true;
                        return true;
                    }
                    waitTime = msecs - (System.currentTimeMillis() - start);
                    if (waitTime <= 0) return false;
                }
            } catch (InterruptedException ex) {
                notify();
                throw ex;
            }
        }
    }
}

關鍵設計細節

  1. 非重入:同一線程重複 acquire() 會死鎖,簡化實現,效能更高
  2. 雙重檢查中斷:進入 synchronized 前後各檢查一次 Thread.interrupted(),響應更及時
  3. wait/notify 機制:建立在 synchronized(this) 監視器上,經典條件變量模式
  4. release() 無條件喚醒:不檢查是否持有鎖,簡化邏輯,允許「過度釋放」
  5. attempt() 精確超時控制:動態計算剩餘等待時間,避免過度/不足等待

Sync 體系主要實現

現代替代:java.util.concurrent.locks

JDK 5+ 內建 Lock、ReadWriteLock、Condition,功能更豐富、效能更優、API 更標準。新項目首選 JDK 內建,僅維護舊代碼時研究 Doug Lea 實現。

設計啟示

Sync 介面展示了「面向抽象編程」的威力:上層業務邏輯依賴 Sync,底層可熱插拔 Mutex/Semaphore/ReentrantLock,零修改切換同步策略,這才是框架級設計的風範。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
實現類語義典型場景
Mutex互斥鎖(非重入)跨方法 before/after 同步
Semaphore計數信號量資源池控制、限流
ReentrantLock可重入鎖替代 synchronized、公平鎖
Latch / CountDown閘/倒數閘多線程啟動同步、階段等待