java.util.concurrent.locks.LockSupport 是構建鎖與同步器的基礎執行緒阻塞原語,提供 park()(阻塞)與 unpark()(喚醒)方法,解決 Thread.suspend/resume 可能導致的死鎖問題。
每個執行緒關聯一個「許可證」(許可證數量最多 1):
unpark():發放許可證(若已有則保持可用狀態)park():消耗許可證(若無則阻塞等待)unpark() 僅保留一個可用狀態public static void main(String[] args) {
Thread mainThread = Thread.currentThread();
// 先發放許可證,再消耗 → 不阻塞直接通過
LockSupport.unpark(mainThread);
LockSupport.park();
System.out.println("執行緒繼續執行");
}
public static void main(String[] args) throws InterruptedException {
Thread worker = new Thread(() -> {
System.out.println("工作執行緒開始,準備阻塞...");
LockSupport.park(); // 等待許可證
System.out.println("工作執行緒被喚醒,繼續執行");
});
worker.start();
Thread.sleep(1000); // 模擬延遲
System.out.println("主執行緒發放許可證");
LockSupport.unpark(worker); // 喚醒工作執行緒
}
public static void main(String[] args) {
Thread t = Thread.currentThread();
LockSupport.unpark(t); // 發放 1 個許可證
LockSupport.park(); // 消耗 1 個 → 通過
LockSupport.park(); // 無許可證 → 永久阻塞(死鎖)!
System.out.println("不會執行到這裡");
}
結論:LockSupport 不可重入,連續呼叫 park() 需對應相同次數的 unpark()。
Thread t = new Thread(() -> {
LockSupport.park();
System.out.println("阻塞結束,中斷狀態:" + Thread.currentThread().isInterrupted());
});
t.start();
Thread.sleep(100);
t.interrupt(); // 中斷阻塞中的執行緒
行為:park() 會響應中斷,執行緒中斷狀態設為 true,但不拋出 InterruptedException。
| 方法 | 說明 |
|---|---|
| parkNanos(long nanos) | 納秒級超時阻塞 |
| parkUntil(long deadline) | 截止時間阻塞(毫秒時間戳) |
| park(Object blocker) | 關聯阻塞器物件,供診斷工具識別 |
| getBlocker(Thread t) | 取得執行緒最近阻塞器物件 |
| 特性 | LockSupport | Object.wait/notify |
|---|---|---|
| 鎖綁定 | 無需 synchronized | 需持有物件鎖 |
| 許可證機制 | 有(不可累積) | 無 |
| 虛假喚醒 | 無 | 可能發生 |
| 中斷處理 | 設置中斷旗標 | 拋出 InterruptedException |
| 適用場景 | 構建同步器、AQS 基礎 | 簡單執行緒協作 |
LockSupport 是 AbstractQueuedSynchronizer (AQS) 核心阻塞機制:
// AQS 內部節點阻塞邏輯簡化
static final class Node {
Thread thread;
// ...
}
// 入隊後阻塞等待
LockSupport.park(this); // 關聯自身節點作為 blocker
// 釋放鎖時喚醒後繼節點
LockSupport.unpark(node.next.thread);
blocker 參數讓監控工具(如 jstack)能顯示執行緒阻塞原因,提升可觀測性。
blocker 參數提升除錯能力Thread.interrupted() 而非捕獲異常