欢迎来到《王者并发课》,本文是该系列文章中的第7篇。
在前面的文章中,我们已经体验过synchronized的用法,并对锁的概念和原理做了简单的介绍。然而,你可能已经察觉到,有一个概念似乎总是和synchronized、锁这两个概念如影相随,很多人也比较喜欢问它们之间的区别,这个概念就是Monitor,也叫监视器。
所以,在讲解完synchronized、锁之后,文本将为你讲解Monitor,揭示它们之间那些公开的秘密,希望你不再迷惑。
首先,你要明白的是,Monitor作为一种同步机制,它并非Java所特有,但Java实现了这一机制。
为了具象地理解Monitor这一抽象概念,我们先来分析身边的一个常见场景。
一、从医院排队就诊机制理解Monitor
相信你一定有过去医院就诊的经历。我们去医院时,情况一般是这样的:
- 首先,我们在门诊大厅前台或自助挂号机进行挂号;
- 随后,挂号结束后我们找到对应的诊室就诊:
- 诊室每次只能有一个患者就诊;
- 如果此时诊室空闲,直接进入就诊;
- 如果此时诊室内有患者正在就诊,那么我们进入候诊室,等待叫号;
- 就诊结束后,走出就诊室,候诊室的下一位候诊患者进入就诊室。
这个就诊过程你一定耳熟能详,理解起来必然毫不费力气。我们做了一张图展示图下:
仔细看这幅图中的就诊过程,如果你理解了这个过程,你就理解了Monitor. 这么简单吗?不要怀疑自己,是的。你竟然早已理解Monitor机制!
不要小看这个机制,它可是生活中的智慧体现。在这个就诊机制中,它起到了两个关键性的作用:
- 互斥(mutual exclusion ):每次只允许一个患者进入候诊室就诊;
- 协作(cooperation):就诊室中的患者就诊结束后,可以通知候诊区的下一位患者。
明白了吗?你在医院就诊的过程竟然和Monitor的机制几乎一模一样。我们换个方式来描述Monitor在计算机科学中的作用:
- 互斥(mutual exclusion ):每次只允许一个线程进入临界区;
- 协作(cooperation):当临界区的线程执行结束后满足特定条件时,可以通知其他的等待线程进入。
而就诊过程中的门诊大厅、就诊室、候诊室则恰好对应着Monitor中的三个关键概念。其中:
- 门诊大厅:所有待进入的线程都必须先在**入口(Entry Set)**挂号才有资格;
- 就诊室:一个每次只能有一个线程进入的特殊房间(Special Room);
- 候诊室:就诊室繁忙时,进入等待区(Wait Set);
我们把上面的图稍作调整,就可以看到Monitor在Java中的模样:
对比来看,相信你已经很直观地理解Monitor机制。再一回味,你会发现synchronized正是对Monitor机制的一种实现。而在Java中,每一个对象都会关联一个监视器。
二、从synchronized源码感受Monitor
既然synchronized是对Monitor机制的一种实现,为了让你更有体感,我们可以写一段极简代码一探究竟。
这段代码极为简单,但是够用,我们在代码中使用了synchronized
关键字:
1 | java复制代码public class SyncMonitorDemo { |
代码写好后,分别执行javac SyncMonitorDemo.java
和 javap -v SyncMonitorDemo.class
,随后你就能得到下面这样的字节码:
1 | yaml复制代码Classfile SyncMonitorDemo.class |
javap
是JDK自带的一个反汇编命令。你可以忽略其他不必要的信息,直接在结果中找到下面这段代码:
1 | yaml复制代码11: monitorenter |
看到monitorenter
和monitorexit
指令,相信智慧的你已经看穿一切。
以上就是文本的全部内容,恭喜你又上了一颗星✨
夫子的试炼
- 写一段包含
synchronized
关键字的代码,使用javap
命令观察结果。
延伸阅读与参考资料
- 《王者并发课》专栏文集下载:github.com/ThoughtsBet…
关于作者
专注高并发领域创作。姊妹篇小册《高并发秒杀的设计精要与实现》作者,关注公众号【MetaThoughts】,及时获取文章更新和文稿。
如果本文对你有帮助,欢迎点赞、关注、监督,我们一起从青铜到王者。
本文转载自: 掘金