经典解释监视器和对象锁

cathy97问:

在JVM的规范中,有这么一些话:  
  “在JVM中,每个对象和类在逻辑上都是和一个监视器相关联的”  
    “为了实现监视器的排他性监视能力,JVM为每一个对象和类都关联一个锁”  
  “锁住了一个对象,就是获得对象相关联的监视器”  
   
  从这些话,看出监视器和对象锁好像是一回事,那为何要定义两个东西,若不一样,他们的关系如何? 

interhanchi的解释:

我觉得讲的很清楚呀.  
  监视器好比一做建筑,它有一个很特别的房间,房间里有一些数据,而且在同一时间只能被一个线程占据,进入这个建筑叫做"进入监视器",进入建筑中的那个特别的房间叫做"获得监视器",占据房间叫做"持有监视器",离开房间叫做"释放监视器",离开建筑叫做"退出监视器".  
  而一个锁就像一种任何时候只允许一个线程拥有的特权.  
  一个线程可以允许多次对同一对象上锁.对于每一个对象来说,java虚拟机维护一个计数器,记录对象被加了多少次锁,没被锁的对象的计数器是0,线程每加锁一次,计数器就加1,每释放一次,计数器就减1.当计数器跳到0的时候,锁就被完全释放了.  
   
  java虚拟机中的一个线程在它到达监视区域开始处的时候请求一个锁.JAVA程序中每一个监视区域都和一个对象引用相关联.  
   
  去看一下深入java虚拟机吧,里面这个讲的很清楚! 

taolei的解释:

活活,这中文翻译的也真够直接的。  
  监视器:monitor  
  锁:lock(JVM里只有一种独占方式的lock)  
  进入监视器:entermonitor  
  离开/释放监视器:leavemonitor  
  (entermonitor和leavemonitor是JVM的指令)  
  拥有者:owner  
   
  在JVM里,monitor就是实现lock的方式。  
  entermonitor就是获得某个对象的lock(owner是当前线程)  
  leavemonitor就是释放某个对象的lock  

### Java对象头、机制与监视器的关系详解 在Java中,对象头(Object Header)是每个Java对象的核心组成部分之一,它存储了对象的元数据信息。这些信息包括但不限于对象的哈希码、GC分代年龄以及状态等[^1]。对象头的设计直接影响了Java机制监视器的实现。 #### 对象头的作用 Java对象头主要由两部分组成:Mark WordKlass Pointer。其中,Mark Word用于存储对象的运行时数据,例如哈希码、GC分代年龄、标志位等;而Klass Pointer则指向该对象的类元数据。对于机制来说,Mark Word尤为重要,因为它记录了当前对象状态,比如是否被加的类型(偏向、轻量级或重量级)等[^5]。 #### 机制与对象头的关系 Java中的机制依赖于对象头中的Mark Word来管理的状态。当一个线程尝试获取某个对象时,JVM会检查该对象头中的标志位,并根据当前情况决定是否能够成功获取。如果当前没有其他线程持有该,则线程可以直接获得并更新对象头中的相关信息;如果有竞争,则可能需要升级或者阻塞等待。 - **内置(synchronized关键字)**:这是Java语言层面提供的最基础的机制,基于对象监视器(Monitor)。当使用`synchronized`修饰方法或代码块时,实际上是在访问受保护的资源之前获取目标对象上的监视器[^2]。 - **显式Lock接口)**:除了`synchronized`之外,Java还提供了更灵活的机制,如`ReentrantLock`。这类通常位于`java.util.concurrent.locks`包下,它们同样利用了底层的操作系统Mutex Lock,但提供了更多的功能支持[^2]。 #### 监视器(Monitor)的角色 监视器是一种同步工具,它确保在同一时刻只有一个线程可以执行特定的代码段。在Java中,每个对象都关联着一个监视器(Monitor),这个是由JVM内部维护的。当线程进入由`synchronized`关键字保护的方法或代码块时,它必须先取得相应的监视器。一旦线程获得了监视器,就可以继续执行临界区内的代码,直到正常退出或抛出异常才会释放。如果多个线程同时试图获取同一个监视器,则只有其中一个线程能够成功获取,其余线程将被阻塞,直到被释放[^4]。 #### 偏向的工作原理 为了提高性能,Java引入了偏向这一优化策略。偏向假设了一个场景:大多数情况下,一个总是由同一个线程多次访问。因此,在第一次使用CAS操作将线程ID设置到对象头之后,后续该线程再次进入临界区时无需进行复杂的同步操作,只需简单地验证对象头中的线程ID是否匹配即可确认所有权[^3]。这种方式减少了不必要的CAS操作上下文切换开销,从而提升了程序的整体效率。 综上所述,Java对象头不仅承载了对象的基本属性,也是实现高效并发控制的关键所在。通过合理设计对象头结构以及巧妙运用各种优化技术,Java能够在保证线程安全的同时尽可能降低多线程环境下的性能损耗。 ```java static final Object obj = new Object(); public static void m1() { synchronized (obj) { // 同步块 A m2(); } } public static void m2() { synchronized (obj) { // 同步块 B m3(); } } public static void m3() { synchronized (obj) { } // 同步块 C } ``` 在这段示例代码中,`m1`, `m2`, `m3` 方法均使用了相同的对象`obj`作为来同步其各自的方法体。这表明这三个方法之间存在共享资源的竞争关系,任何时刻只能有一个线程通过`synchronized`语句进入这些方法中的任意一个。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值