Lock lock = new ReentrantLock();
lock.lock(); // 阻塞獲取
lock.unlock(); // 釋放
lock.tryLock(); // 非阻塞嘗試,立即返回 true/false
lock.tryLock(1, TimeUnit.SECONDS); // 帶超時嘗試
lock.lock();
try {
// 臨界區代碼
} finally {
lock.unlock(); // 必須在 finally 中釋放
}
同一執行緒可重複獲取已持有的鎖(持有計數器 +1)。被鎖保護的方法可安全呼叫另一個使用同一鎖的方法。
public void run() {
lock.lock();
try {
sayHello(); // 內部再次 lock.lock(),同一執行緒通行無阻
} finally { lock.unlock(); }
}
public void sayHello() {
lock.lock();
try { ... } finally { lock.unlock(); }
}
輸出證明:WorkerTwo 先進入 run(),再呼叫 sayHello(),WorkerOne 等待釋放後才進入。
| 特性 | Object.wait/notify | Condition |
|---|---|---|
| 綁定鎖 | 隱式綁定物件監視器 | 顯式綁定 Lock(lock.newCondition()) |
| 等待隊列 | 單一 | 可建立多個 Condition 實現多隊列 |
| 喚醒精度 | notify() 隨機、notifyAll() 全喚醒 | signal() 單喚醒、signalAll() 全喚醒,針對特定隊列 |
| 方法名 | wait/notify/notifyAll | await/signal/signalAll |
// 等待方
lock.lock();
try {
while (!conditionMet) { // 防止虛假喚醒,必須用 while
condition.await();
}
// 執行任務
} finally { lock.unlock(); }
// 通知方
lock.lock();
try {
conditionMet = true;
condition.signalAll(); // 或 signal()
} finally { lock.unlock(); }
public class ConditionDemo {
static class Shared {
final Lock lock = new ReentrantLock();
final Condition notEmpty = lock.newCondition();
boolean hasTask = false;
}
static class Producer extends Thread {
private final Shared s;
Producer(Shared s) { this.s = s; }
public void run() {
while (true) {
s.lock.lock();
try {
s.hasTask = true;
s.notEmpty.signalAll();
System.out.println("Producer: task ready");
} finally { s.lock.unlock(); }
sleep(2000);
}
}
}
static class Consumer extends Thread {
private final Shared s;
Consumer(Shared s) { this.s = s; }
public void run() {
while (true) {
s.lock.lock();
try {
while (!s.hasTask) s.notEmpty.await();
System.out.println("Consumer: task done");
s.hasTask = false;
} finally { s.lock.unlock(); }
}
}
}
public static void main(String[] args) {
Shared s = new Shared();
new Producer(s).start();
new Consumer(s).start();
}
}
輸出完美交替:Producer: task ready → Consumer: task done → ...
tryLock、可中斷、公平鎖、多 Condition 等進階能力,OO 設計更清晰。notifyAll 唤醒無關執行緒的效能浪費。