在Java中,监视器(Monitor)是一种同步机制,用于控制多线程环境下对共享资源的访问,它通过内置锁(synchronized
)和线程通信方法(wait()
, notify()
, notifyAll()
)实现线程安全,以下是详细实现方法:
监视器的核心:synchronized 关键字
Java 中每个对象都有一个内置锁(Monitor Lock),通过 synchronized
关键字触发:
-
同步代码块
锁定指定对象:public void safeMethod() { synchronized (lockObject) { // lockObject 是任意对象 // 临界区代码(共享资源操作) } }
-
同步方法
锁定当前实例(this
)或类(静态方法):public synchronized void safeMethod() { // 操作共享资源 } public static synchronized void staticSafeMethod() { // 静态方法锁定 Class 对象 }
线程通信:wait() 与 notify()
监视器通过 wait()
和 notify()
实现线程间协作:
wait()
释放锁并让线程进入等待状态(需在synchronized
块内调用):synchronized (lockObject) { while (条件不满足) { lockObject.wait(); // 释放锁,线程等待 } // 条件满足后继续执行 }
notify()
/notifyAll()
唤醒等待线程(notify()
随机唤醒一个,notifyAll()
唤醒所有):synchronized (lockObject) { // 改变条件 lockObject.notify(); // 唤醒一个等待线程 // 或 lockObject.notifyAll(); }
完整示例:生产者-消费者模型
import java.util.LinkedList; import java.util.Queue; public class MonitorExample { private final Queue<Integer> queue = new LinkedList<>(); private final int CAPACITY = 5; private final Object lock = new Object(); // 监视器锁对象 // 生产者 public void produce(int item) throws InterruptedException { synchronized (lock) { while (queue.size() == CAPACITY) { lock.wait(); // 队列满时等待 } queue.add(item); System.out.println("生产: " + item); lock.notifyAll(); // 唤醒消费者 } } // 消费者 public void consume() throws InterruptedException { synchronized (lock) { while (queue.isEmpty()) { lock.wait(); // 队列空时等待 } int item = queue.poll(); System.out.println("消费: " + item); lock.notifyAll(); // 唤醒生产者 } } }
关键注意事项
- 避免死锁
- 确保锁的获取顺序一致。
- 使用超时机制:
wait(long timeout)
。
- 使用
while
而非if
检查条件
防止虚假唤醒(Spurious Wakeup),重复检查条件。 - 优先用
notifyAll()
notify()
可能因唤醒错误线程导致死锁。 - 锁粒度优化
减小同步代码块范围,提升性能(如避免在synchronized
内执行耗时操作)。 - 替代方案
复杂场景推荐java.util.concurrent
包(如ReentrantLock
、Condition
)。
监视器的工作原理
- 当线程进入
synchronized
块时,获取对象的监视器锁。 - 若锁已被占用,线程进入阻塞队列(Entry Set) 等待。
- 线程调用
wait()
后,释放锁并进入等待队列(Wait Set)。 - 其他线程调用
notify()
时,等待队列中的线程移至阻塞队列,重新竞争锁。
Java 的监视器机制通过 synchronized
+ wait()/notify()
实现线程同步与协作,正确使用时需注意:
- 锁范围最小化以提升性能。
- 用
while
循环检查条件,避免虚假唤醒。 - 高并发场景优先使用
java.util.concurrent
工具类(如BlockingQueue
)。
引用说明基于 Oracle 官方文档 Java Concurrency 和 Brian Goetz 所著《Java Concurrency in Practice》,实践代码遵循线程安全最佳实践,适用于 JDK 8 及以上版本。
原创文章,发布者:酷盾叔,转转请注明出处:https://www.kd.cn/ask/45993.html