Doug Lea Concurrent 套件定義 Sync 介面作為所有同步原語(鎖、閘門、條件變數)的統一抽象,Mutex 是其最基礎的非重入互斥鎖實現。本文剖析源碼並示範精細鎖定鏈表應用。
public interface Sync {
void acquire() throws InterruptedException; // 獲取許可(阻塞)
boolean attempt(long msecs) throws InterruptedException; // 嘗試獲取(超時)
void release(); // 釋放許可
}
優勢:超越 synchronized 的方法/區塊限制,鎖物件可跨方法、跨物件傳遞,實現靈活的同步控制。
class X {
Sync gate; // Mutex 或其他 Sync 實現
public void m() {
try {
gate.acquire();
try {
// 臨界區邏輯
} finally {
gate.release(); // 即使拋出異常也能釋放
}
} catch (InterruptedException ex) {
// 處理中斷
}
}
}
release() 不拋出 InterruptedException,適合放在 finally 中。
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(); // 自旋等待
inuse = true;
} catch (InterruptedException ex) {
notify(); // (2) 被中斷時喚醒其他等待者
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; // (3) 超時返回
}
} catch (InterruptedException ex) {
notify(); throw ex;
}
}
}
}
acquire() 開頭與 wait() 捕獲處均檢查中斷狀態。Thread.interrupted() 清除標誌位,若線程已被中斷則立即拋出異常,避免進入等待狀態。InterruptedException 後呼叫 notify() 喚醒其他等待者,防止信號遺失導致永久阻塞。attempt() 基於 Object.wait(long) 實現,非精確時鐘,僅供粗略超時控制。每個節點持有獨立 Mutex,實現「手把手」鎖遞移,大幅提升並行遍歷效能:
class Node {
Object item; Node next;
Mutex lock = new Mutex(); // 每節點一把鎖
Node(Object x, Node n) { item = x; next = n; }
}
class List {
protected Node head;
protected synchronized Node getHead() { return head; } // 僅保護 head 參考
boolean search(Object x) throws InterruptedException {
Node p = getHead();
if (p == null) return false;
p.lock.acquire(); // 獲取首節點鎖
try {
for (;;) {
if (x.equals(p.item)) { p.lock.release(); return true; }
Node nextp = p.next;
if (nextp == null) { p.lock.release(); return false; }
try { nextp.lock.acquire(); } // 先獲取下一節點鎖
catch (InterruptedException ex) { p.lock.release(); throw ex; }
p.lock.release(); // 再釋放當前節點鎖
p = nextp;
}
} finally { /* 確保釋放 */ }
}
synchronized void add(Object x) { head = new Node(x, head); }
}
Mutex 實現 Sync 介面,提供非重入、可中斷、可超時的互斥語義synchronized + wait/notify + 狀態旗標java.util.concurrent.locks.ReentrantLock(JDK 1.5+ 內建,支援重入、公平性、條件變數等進階特性)