Difference between lock and monitor – Java Concurrency
编者注:本文为历史博文归档;涉及 JDK、框架与工具链版本请以当前官方文档为准。引用外链图片可能失效,阅读时请注意时效性。
在面试中,您可能会遇到这样的问题:锁(Lock)和监视器(Monitor)之间有什么区别? 要回答这个问题,必须对 Java 多线程在后台的工作机制有足够的了解。
答案其实很简短:锁为实现监视器提供了必要的支持。 详细的解释如下。
锁(Lock)
锁是一种数据结构,逻辑上是堆内存中对象标头(Object Header)的一部分。JVM 中的每个对象都具有此锁(或称互斥锁,Mutex),任何程序均可使用该锁来协调对对象的多线程访问。
- 所有权机制:如果有任何线程想要访问该对象的实例变量,线程必须首先“拥有”对象的锁(即在锁存储区中设置特定标志)。
- 阻塞机制:试图访问该对象变量的所有其他线程必须等待,直到拥有锁的线程释放该对象的锁(取消设置标志)。
- 可重入性:线程拥有锁后,它可以多次请求相同的锁。但是在将锁提供给其他线程之前,必须释放相同的次数。例如,如果一个线程请求了三次锁,则该线程将继续拥有该锁,直到它“释放”了三次。
请注意,当线程明确要求锁时,它是由线程获得的。在 Java 中,这是通过 synchronized 关键字或通过 wait() 和 notify() 方法来完成的。
监视器(Monitor)
监视器是一种同步构造,它允许线程具有互斥(使用锁)和协作功能。即使线程能够等待某些条件成立(使用等待集,Wait-Set),监视器也能管理这些行为。
换句话说,连同实现锁的数据,每个 Java 对象在逻辑上均与实现等待集的数据相关联。
- 锁的作用:帮助线程在共享数据上独立工作而不会互相干扰。
- 等待集的作用:帮助线程相互协作,共同朝着一个目标努力。例如,所有等待线程都将移至该等待集,并在锁定被释放后收到通知。
此等待集通过锁(互斥量)的辅助来帮助构建监视器。
互斥(Mutual Exclusion)
用简单的话来说,监视器就像一栋建筑物,其中包含一个特殊的房间(对象实例),一次只能占用一个线程。房间中通常包含一些需要防止并发访问的数据。
- 进入监视器:从线程进入该房间的时间到它离开的时间,它都可以独占访问该房间中的任何数据。
- 获取监视器:进入建筑物内的特殊房间。
- 拥有监视器:占领房间。
- 释放监视器:离开房间。
- 退出监视器:离开整个建筑物。
当线程到达以访问受保护的数据(进入特殊房间)时,首先将其放入建筑物接收队列中(入口集,Entry Set)。
- 如果没有其他线程在等待(监视器未被拥有),则该线程获取锁并继续执行受保护的代码。
- 线程完成执行后,它将释放锁并退出建筑物(退出监视器)。
如果一个线程到达并且另一个线程已经拥有监视器,则它必须在接收队列中等待(入口集)。当前所有者退出监视器时,新到达的线程必须与也在入口集中等待的任何其他线程竞争。只有一个线程会赢得比赛并拥有锁。
注意:在单纯的互斥场景中,等待集(Wait Set)并不发挥作用。
协作(Cooperation)
通常,互斥仅在多个线程共享数据或其他资源时才重要。如果两个线程不使用任何公共数据或资源,则它们通常不会相互干扰,也不必以互斥的方式执行。互斥有助于防止线程在共享数据时相互干扰,而协作则可以帮助线程一起朝着某个共同的目标努力。
当一个线程需要某些数据处于特定状态,而另一个线程负责使数据进入该状态时,合作非常重要。例如生产者/消费者问题:
- 读取线程需要缓冲区处于“非空”状态才可以从缓冲区读取任何数据。如果读取线程发现缓冲区为空,则必须等待。
- 写线程负责用数据填充缓冲区。一旦写入线程完成了写入操作,读取线程便可以进行更多读取操作。
有时也称为“等待并通知(Wait and Notify)”或“发出信号并继续(Signal and Continue)”监视器。因为它保留了监视器的所有权,并在需要时继续执行监视器区域。在稍后的某个时间,通知线程释放监视器,并且等待线程恢复拥有该锁。
这种合作需要入口集(Entry Set)和等待集(Wait Set)。下面给出的图将帮助您理解这种合作。

上图将监视器显示为三个矩形:
- 中心:一个大矩形包含一个线程,即监视器的所有者。
- 左侧:一个小矩形包含入口集(Entry Set)。
- 右侧:另一个小矩形包含等待集(Wait Set)。
希望以上讨论将有助于您获得更多见解。欢迎随时提问。
学习愉快!
说明:本文基于 Java concurrency 基础理论撰写。JDK 不同版本中对于对象锁的具体实现(如偏向锁、轻量级锁等优化)可能存在差异,请以当前官方文档为准。
版权声明:本文为原创文章,版权归 戴老师的博客 所有,转载请联系博主获得授权。
本文地址:https://1diff.fun/archives/difference-between-lock-and-monitor--java-concurrency.html
如果对本文有什么问题或疑问都可以在评论区留言,我看到后会尽量解答。