java 中的各种锁原理介绍 之 Synchronized

Synchronized

轻量级锁基于java自身实现,重量级锁依赖系统底层互斥量实现

太长不看,这里有总结, 整个流程在文章末尾有流程图

Synchronized 中有几种锁,听起来感觉这话有点怪,Synchronized本身不就是一种锁吗?是的,但是JVM内置锁在1.5之后版本做了重大的优化,存在一个锁的膨胀升级过程,下面会一一介绍

  1. 偏向锁,基于Mark Word实现 ,Mark Word 底下有介绍
  2. 轻量级锁,所谓轻量级锁是基于对象头Mark Word实现的,这里升级为轻量锁其实就是Mark Word 的结构变更以及自旋,如果获取失败会进行自旋,自旋就是个while循环,不需要放弃cpu的使用权和发生线程切换等操作,所以轻量
  3. 重量级锁 基于 系统底层的互斥量实现,需要发生陷入内核态,产生线程切换等成本

java 一个对象的组成

img

image-20200915173517945

  • 对象头存储的就是一些对象自身的数据,指向哪个类,以此来判断一个对象是哪个类的实例,Mark Word等
  • 实例就是用户new 的那的个东西,储存着对象的实际数据,也就是我们在程序中定义的各种类型的字段内容。
  • 对象填充因为JVM要求java的对象占的内存大小应该是8bit的倍数,所以后面有几个字节用于把对象的大小补齐至8bit的倍数,没有特别的功能。

说说Monitor对象,在对象的对象头中,当锁的状态为重量级锁的时候,它的指针即指向monitor对象

MonitorEnter指令:插入在同步代码块的开始位置,当代码执行到该指令时,将会尝试获取该对象Monitor的所有权,即尝试获得该对象的锁;
MonitorExit指令:插入在方法结束处和异常处,JVM保证每个MonitorEnter必须有对应的MonitorExit;

monitorenter

  1. 如果monitor的进入数为0,则线程进入到monitor,然后将进入数设置为1,该线程称为monitor的所有者。
  2. 如果是线程已经拥有此monitor(即monitor进入数不为0),然后该线程又重新进入monitor,则将monitor的进入数+1,这个即为锁的重入
  3. 如果其他线程已经占用了monitor,则该线程进入到阻塞状态,直到monitor的进入数为0,该线程再去重新尝试获取monitor的所有权

monitorexit:执行该指令的线程必须是monitor所有者,指令执行时,monitor进入数-1,如果-1后进入数为0,那么线程退出monitor,不再是这个monitor的所有者。这个时候其它阻塞的线程可以尝试获取monitor的所有权。

image-20200915173123709

锁的膨胀升级过程:

锁的状态总共有四种,无锁状态、偏向锁、轻量级锁和重量级锁。随着锁的竞争,锁可以从偏向锁升级到轻量级锁,再升级的重量级锁,但是锁的升级是单向的,也就是说只能从低到高升级,不会出现锁的降级。

对下图的理解:

当只有一个线程执行的时候,获取偏向锁,出现锁竞争时,撤销偏向锁,升级为轻量锁,获取轻量锁失败时进行自旋,自旋失败升级为重量锁

img

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值