07.管程Monitor
总结
- 管程封装共享变量及操作,同时解决互斥(入口队列)和同步(条件变量等待队列)
- Java 采用 MESA 模型:notify 后通知方继续执行,被唤醒方进入入口队列重新竞争
- MESA 的代价:被唤醒后条件不一定满足,必须用
while重新判断 synchronized是管程的隐式实现,Lock+Condition 是显式实现
管程(Monitor):管理共享变量及其操作过程,使其支持并发。Java 选择了比信号量更易用的管程模型。synchronized + wait/notify 是管程的隐式实现,Lock + Condition 是显式实现,AQS 也是管程思想的体现。
1. MESA 模型
管程解决两个核心问题:
互斥:将共享变量及操作封装,同时只允许一个线程进入。
同步:一个入口队列(Entry Set)+ 每个条件变量对应一个等待队列(Wait Set)。
三种通知模型对比
| 模型 | notify 时机 | 特点 |
|---|---|---|
| Hasen | 代码最后 | T2 通知后自己结束,T1 运行 |
| Hoare | 任意位置 | T2 通知后阻塞,T1 执行完唤醒 T2 |
| MESA(Java 采用) | 任意位置 | T2 通知后继续执行,T1 进入入口队列重新竞争 |
MESA 的坏处:T1 被唤醒后条件不一定还满足,必须用 while 重新判断(见 06.等待-通知机制)。
2. synchronized 与管程的对应关系
synchronized锁住的对象 → 管程实例- 竞争失败的线程 → 进入 Entry Set(左边队列)
- 调用
wait()的线程 → 进入 Wait Set(右边队列) notify()/notifyAll()→ 将 Wait Set 的线程移回 Entry Set 重新竞争- 锁哪个对象,就调用哪个对象的 wait/notify