java filemonitor 多层_Java Monitor(管程)

操作系统在面对线程间同步的时候,会支持例如semaphore信号量和mutex互斥量等同步原语,而monitor是在编程语言中被实现的,下面介绍一下java中monitor(监视器/管程:管理共享变量以及对其的操作过程,让他们支持并发)的实现原理:

dcfd18ccdf69e2e2c9b083ad859fe1cc.png

以一个阻塞队列的实现来举例:

f6b437745df781c63ecdff883d6e74e4.png

同时,java内置的synchronized关键字可以认为是MESA模型的简化版,其只能有一个条件变量,但编译器会自动添加加锁与解锁的代码。synchronized关键字可以修饰实例方法、类方法以及代码块,如果修饰的是代码块,需要制定关联的Object;如果修饰的是实例方法,那么其关联的对象实际上是this;如果修饰的是类方法,那么其关联的对象是this.class。这些关联的对象就是MESA模型里的条件变量。

synchronized实现原理

JVM基于进入和退出monitor对象来实现同步,同步代码块采用添加moniterenter、moniterexit,同步方法使用ACC_SYNCHRONIZED标记符隐式实现。每个对象都有一个monitor与之关联,运行到moniterenter时尝试获取对应monitor的所有权,获取成功就将monitor的进入数加1(所以是可重入锁,也被称为重量级锁),否则就阻塞,拥有monitor的线程运行到moniterexit时进入数减1,为0时释放monitor。

java中每个对象都有一个对象头,synchronized所用的锁就是存在对象头里的。如果是非数组的对象是8个字节(32位JVM)或者16字节(64位JVM),数组对象还会有一个数组长度(4个字节)。以32位JVM非数组对象为例:

847bff4d8e41bec3660fb3b83027fe0f.png

锁信息就存在前4个字节的MarkWord中,JVM对synchronized的加锁过程优化为:

检测Mark Word里面是不是当前线程的ID,如果是,表示当前线程处于偏向锁

如果不是,则使用CAS将当前线程的ID替换Mard Word,如果成功则表示当前线程获得偏向锁,置偏向标志位1

如果失败,则说明发生竞争,撤销偏向锁,进而升级为轻量级锁。

当前线程使用CAS将对象头的Mark Word替换为锁记录指针,如果成功,当前线程获得锁

如果失败,表示其他线程竞争锁,当前线程便尝试使用自旋来获取锁。

如果自旋成功则依然处于轻量级状态。

如果自旋失败,则升级为重量级锁。

重量级锁是悲观锁的一种,自旋锁、轻量级锁与偏向锁属于乐观锁。

CAS设计读取-比较-写入三个操作,是在CPU指令层面保证其原子性,volatile是保证多线程下的内存可见性,二者需配合使用。另外还需注意CPU缓存行(一次以32/64字节为单位从主内存中读取数据到缓存)包含多个变量所带来的隐形同步问题:其中一个变量被volatile修饰,导致另外一个变量在另一个CPU核上(另一个线程)的读写也要被强制刷新缓存。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值