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

Java 並發新同步機制(一):ReentrantLock 重入鎖與 Condition 條件變數

     編輯:Java 相關知識

1. ReentrantLock:synchronized 的強化版

核心 API

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 等待釋放後才進入。

2. Condition:取代 wait/notify 的精準協作工具

核心差異

特性Object.wait/notifyCondition
綁定鎖隱式綁定物件監視器顯式綁定 Lock(lock.newCondition())
等待隊列單一可建立多個 Condition 實現多隊列
喚醒精度notify() 隨機、notifyAll() 全喚醒signal() 單喚醒、signalAll() 全喚醒,針對特定隊列
方法名wait/notify/notifyAllawait/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 → ...

總結

  • ReentrantLock:提供 tryLock、可中斷、公平鎖、多 Condition 等進階能力,OO 設計更清晰。
  • Condition:將「等待條件」物件化,支援多隊列精準喚醒,解決 notifyAll 唤醒無關執行緒的效能浪費。
  • 兩者結合是構建高效能併發組件(如阻塞隊列、信號量、閂鎖)的基石。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved