Java重量级对象和轻对象,Java知识进阶-程序员应该死磕的Monitor知识点-知识铺

1df832b587d65ca4316af9b4f14bfb3f.png

知识铺: 致力于打造轻知识点,持续更新每次的知识点较少,阅读不累。不占太多时间,不停的来唤醒你记忆深处的知识点。

一、Moniter 场景

1.1 Java 线程同步

由于多线程对资源的访问引发的可见性和原子性带来的安全问题。同步锁,互斥锁,都可以保证同一时刻只有一个线程访问。 这里用到的机制就是都是对资源的监视锁,即Monitor,每个对象都用于自己的监视锁Monitor.

1.2  对象中的锁标识

在Java 对象模型中讲到,每个对象的头部都有三部分组成:Mark Word 、Klass Word、数组长度。 每个对象的锁标识,就在 Mark Word这部分中。 如下图:

d1ff725b6deb069920897384b88b9339.png

1.2.1 正常:  biased_lock 0 偏向锁标识       + lock 锁标识 01

1.2.2 偏向锁:    biased_lock 1 偏向锁标识 + lock 锁标识 01

1.2.3 轻量级锁:ptr_to_lock_record  锁指针 +  lock 锁标识 00

1.2.4 重量级锁:ptr_to_heavyweight_monitor 锁指针 + lock 锁标识 10

1.2.5 进入GC:   lock 锁标识 11

二、ObjectMonitor 结构

前面讲到  java.lang.Object 类定义了 wait(),notify(),notifyAll() 方法。 这些都是 native方法,底层是C++来实现的。 这些方法的具体实现,依赖一个叫做ObjectMonitor模式实现,这是JVM内部C++实现的机制。

gif;base64,R0lGODlhAQABAIAAAP

这里有几个比较重要的字段

2.1  _owner  指向持有ObjectMonitor对象的线程地址。

2.2  _WaitSet 存放调用wait方法,而进入等待状态的线程的队列。

2.3 _EntryList 这里是等待锁block状态的线程的队列。

2.4 _recursions 锁的重入次数。

2.5 _count 线程获取锁的次数。

gif;base64,R0lGODlhAQABAIAAAP

三、 Monitor 上锁 释放锁

3.1 上锁过程

3.1.1 线程获取资源对象的锁,判断 _owner是否为空。这里操作是通过 CAS操作:比较和交换(Conmpare And Swap),比较新值和旧值的不同,替换,这里会发生ABA问题,接下来文章会详细说明。

3.1.2 如果 _owner为null ,直接把其赋值,指向自己, _owner = self ,同时把重入次数 _recursions = 1, 获取锁成功。

3.1.3 如果 _self == cur 和当前线程一致,说明是重入了, _recursions++ 即可

3.1.4 线程进入对象资源,处理。 同时等待当前线程的释放信号,期间一致持有对象资源的锁。

3.2 释放锁

3.2.1  通过 ObjectMonitor::exit 退出

3.2.2 把线程插入到_EntryList中 _recursions--

3.2.3 再次从 _EntryList 中取出线程

3.2.4 调用unpark退出

具体代码,可以搜索 objectMonitor.cpp ,查看源码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值