为什么 Monitor 是线程私有的数据结构?

以下是我对 monitor 的理解:

  1. 每个对象都关联一个 monitor
  2. 内置锁 也叫 监视器锁/Monitor锁/Monitor
  3. Monitor其实是一种同步机制, 主要特点是: 同步(互斥), 协作(等待 + 唤醒)
  4. JVM 中的Monitor的实现: 互斥访问: 接口为synchronized; 线程协作: 接口为Object.waitObject.notify/notifyAll

我在 https://juejin.im/post/5cc6621bf265da038364d05c 这篇文章中又看到他说 Monitor是线程私有的数据结构.

我对 monitor 的知识了解的非常混乱, 如果大家有好的文章或书, 可以和我说一下 谢谢### 问题描述

最佳答案

首先祭出官方文档:https://docs.oracle.com/javas...

对于 Monitor 的定义,文档是这么说的:

Each object in Java is associated with a monitor, which a thread can lock or unlock.
Java 中的每个对象都有一个 monitor 与之关联,该 monitor 可以被线程加锁和解锁。

可以得知,monitor 不是对象概念的一部分,但与对象一对一存在,而且可以被线程访问和操作。

然后文档接着描述:

Only one thread at a time may hold a lock on a monitor. Any other threads attempting to lock that monitor are blocked until they can obtain a lock on that monitor.
同一时间只有一个线程可以持有该 monitor 的锁。其他试图对该 monitor 加锁的线程都将阻塞,直到它们可得到该 monitor 的锁为止。

这段话包含了一个意思,就是 monitor 还有一个对应的锁的概念,所以 monitor 本身并不是锁吗?在搜索之后我又从另一个官方文档中找到了一句话:

https://docs.oracle.com/javas...

Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.")
线程同步是建立在一个叫做“固有锁”或叫“监视锁”的内部实体之上的(API 规范通常将该实体简称为“monitor”)。

由此可见,“intrinsic lock”、“monitor lock”、“monitor” 实际上指的是同一个东西,它就是锁。英语当中“锁”和“加锁”是同一个词,我猜可能是为了避免混淆,才添加了 monitor 这个概念。

再回到问题本身,“Monitor 是线程私有的数据结构” 这样的描述是错误的,monitor 是与对象关联,但不属于线程所有。

但是问题到此并未结束。关于锁和同步的知识,实际上有三个层面的描述:

  1. 语法和面向对象概念的层面
  2. JVM 规范层面
  3. JVM 实现层面

前面所说的,都是语法层面的锁概念,而这里有个问题是,线程到底如何操作锁。同样看官方文档中的 JVM 规范:

https://docs.oracle.com/javas...

文档中列举了线程与内存(包括主内存与副本内存)之间的操作,其中 lock 和 unlock 都是要操作主内存的,与之对应的字节码指令为 monitorentermonitorexit

最后一个问题,锁到底存放在哪里。这是第三个层面的问题了,其答案取决于 JVM 的实现,Java 规范没有强制要求。以当前最流行的 JVM 实现(即 HotSpot)为例,与一个对象关联的锁状态信息是存放在对象头里面的。具体详情可以在网上进一步搜索。