一、前言
monitor 是 java 中实现 互斥锁(mutual exclusion) 的核心工具。只有一个线程可以持有某个对象的 monitor,其他线程必须阻塞等待,直到该线程释放锁,jvm 中每个对象在重量级锁的情况才关联着一个 monitor,当线程进入 锁等级为重量级的synchronized
代码时,必须先获得该对象的 monitor。
二、monitor 的数据结构
三、monitor 的工作流程
(1)某线程尝试进入同步代码块(monitorenter)
- 如果 monitor 没有被其他线程持有,线程获得锁(成为 owner)。
- 如果已经持有:
- 若是当前线程自身(重入),增加计数器。
- 否则,进入 entry queue 阻塞等待。
(2)退出同步代码块(monitorexit)
- 释放锁:减少计数器;
- 若计数为 0,则清空 owner,并唤醒 entry queue 中的线程开始争夺锁。
(3)调用 wait/notify 时的行为
wait()
:- 当前线程释放锁,加入 wait set,进入等待状态;
notify()
:- 将 wait set 中随机选择一个线程移入 entry queue,等待重新竞争锁。
工作流程图解
线程零抢占到对象obj的锁,此时entryqueue中存放一二三线程等待抢锁
此时对thread-0调用wait()方法,thread-0释放锁并且进入waitset,entryqueue队列中的线程随机获取锁,假设thread-2获取到锁
此时entryqueue中的线程处于阻塞状态(blocked),等待thread-2释放锁再进行抢锁
而此时thread-0线程进入等待状态(waiting或timed_waiting),不参与锁的竞争,只有恢复阻塞状态时才去参与锁的竞争
想要从等待状态恢复为阻塞状态的三种方法
- 其他线程调用
notify()
或notifyall()
唤醒它 - 等待超时(如果使用了
wait(long timeout)
方法) - 被中断(调用
interrupt()
方法)
四、monitor 和锁的演进机制
jvm 为了性能优化,提供了 锁优化策略:
锁类型 | 描述 |
---|---|
无锁 | 默认状态,适用于单线程环境,mark word 存储对象的哈希码、分代年龄等信息。 |
偏向锁 | 偏向于第一个访问线程,后续无竞争,mark word 会被替换为锁标志位(01)和持有锁的线程id |
轻量级锁 | 多线程但无阻塞,通过 cas 竞争
|
重量级锁 | monitor 对象控制,线程进入阻塞队列,性能开销大,mark word 中存储指向 monitor 对象(管程/互斥量)的指针 |
五、monitor 的作用总结表
功能 | 描述 |
---|---|
互斥访问 | 确保同一时间内只有一个线程访问共享资源 |
可重入性 | 同一线程可重复进入临界区 |
线程协作(条件变量) | 支持 wait/notify 机制 |
阻塞调度 | 管理 entry queue 和 wait set 的线程阻塞与唤醒 |
性能优化依据 | 锁升级的核心控制结构 |
到此这篇关于java并发monitor工作原理图解的文章就介绍到这了,更多相关java并发monitor工作原理内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论