在 Java 并發編程中,鎖的等待和喚醒機制至關重要,通常使用 wait()
、notify()
和 notifyAll()
來實現線程間的協調。本文將詳細介紹這些方法的用法,并通過示例代碼加以說明。
1. wait()
、notify()
與 notifyAll()
在 Java 中,Object
類提供了 wait()
、notify()
和 notifyAll()
方法,它們用于線程間的通信。
wait()
:使當前線程進入等待狀態,并釋放鎖。notify()
:喚醒單個等待線程。notifyAll()
:喚醒所有等待線程。
注意,這些方法必須在同步代碼塊(synchronized
)中調用,否則會拋出 IllegalMonitorStateException
。
2. 示例代碼
下面的示例展示了 wait()
和 notify()
的使用。
class SharedResource {private boolean available = false;public synchronized void produce() {while (available) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}System.out.println("Producing an item");available = true;notify();}public synchronized void consume() {while (!available) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}System.out.println("Consuming an item");available = false;notify();}
}public class WaitNotifyExample {public static void main(String[] args) {SharedResource resource = new SharedResource();Thread producer = new Thread(resource::produce);Thread consumer = new Thread(resource::consume);producer.start();consumer.start();}
}
3. wait()
和 notify()
的工作原理
- 生產者線程
produce()
在available
為true
時調用wait()
進入等待狀態,釋放鎖。 - 消費者線程
consume()
在available
為false
時調用wait()
進入等待狀態,釋放鎖。 produce()
生產后調用notify()
喚醒consume()
。consume()
消費后調用notify()
喚醒produce()
。
4. notifyAll()
的使用場景
notify()
僅喚醒一個線程,而 notifyAll()
可用于有多個等待線程的情況,以防止某些線程被永久阻塞。
public synchronized void produce() {while (available) {try {wait();} catch (InterruptedException e) {Thread.currentThread().interrupt();}}System.out.println("Producing an item");available = true;notifyAll();
}
5. Lock
和 Condition
方式
除了 synchronized
,還可以使用 Lock
和 Condition
進行等待和喚醒控制。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;class SharedResourceWithLock {private boolean available = false;private final Lock lock = new ReentrantLock();private final Condition condition = lock.newCondition();public void produce() {lock.lock();try {while (available) {condition.await();}System.out.println("Producing an item");available = true;condition.signal();} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}}public void consume() {lock.lock();try {while (!available) {condition.await();}System.out.println("Consuming an item");available = false;condition.signal();} catch (InterruptedException e) {Thread.currentThread().interrupt();} finally {lock.unlock();}}
}
6. 總結
wait()
和notify()
需要在synchronized
塊中使用。notifyAll()
可防止線程被永久阻塞。Lock
和Condition
提供更靈活的等待和喚醒機制。
合理使用這些機制可以提升 Java 多線程程序的性能和可靠性。