synchronized 实现原理

synchronized 实现原理

synchronized的三种应用方式

  1. 修饰实例方法,作用于当前实例加锁,进入同步代码前要获得当前实例的锁。
  2. 修改静态方法,作用于当前类,进入同步代码前要获得当前类的锁。
  3. 修饰代码块,指定加锁对象,对给定对象加锁,进入同步代码前要获得给定对象。

synchronized的字节码指令

synchronized同步块使用了monitorentermonitorexit指令实现同步,这两个指令本质上是对一个对象的监视器(monitor)进行获取,这个过程是排他的,也就是说同一个时刻只能有一个线程获取到由synchronized所保护对象的监视器(monitor)。

线程执行到monitorenter指令时,会尝试获取对象所对应的monitor所有权,也就是尝试获取对象的锁,而执行monitorexit就是释放monitor的所有权。

synchronized 的锁的原理

两个重要的概念:一个是对象头,另外一个是monitor。

Java 对象头

在Hotspot虚拟机中,对象在内存中的布局分为三块区域:对象头(Mark Word、Class Metadata Address)、实例数据和对齐填充。Java 对象头是实现synchronized的锁对象的基础。一般而言,synchronized使用的锁对象是存储在Java 对象头里。它是轻量级锁和偏向锁的关键。

  • Mark Word 对象头
    对象头用于存储对象自身的运行时数据,如HashCode、GC分代年龄、锁状态标志、线程持有的锁、偏向线程ID、偏向时间戳等等。Java 对象头一般占有2个机器码(32位虚拟机中,1个机器码等于4字节,也就是32 bits)
  • Class Metadata Address 类型指针
    类型指针,即时对象指向它的类的元数据的指针,虚拟机通过这个指针来确定这个对象是哪个类的实例。
  • Array Length 数组长度
    如果对象是一个Java 数组,那在对象头中还必须有一块用于记录数组长度的数据。
    在这里插入图片描述

Monitor

Monitor是一个同步工具,它内置于每个Object对象中,相当于一个许可证,拿到许可证即可进行操作,没有拿到许可证则需要阻塞等待。
在这里插入图片描述

synchronized锁的优化

jdk1.6以后对synchronized的锁进行了优化,引入了偏向锁、轻量级锁,锁的级别从低到高逐步升级

无锁->偏向锁->轻量级锁->重量级锁

自旋锁与自适应自旋锁

线程的挂起和恢复会极大的影响开销。并且jdk官方人员发现,很多线程在等待锁的时候,在很短的一段时间就获得了锁,所以它们在线程等待的时候,并不需要把线程挂起,而是让他无目的的循环,一般设置10次。这样就避免了线程切换的开销,极大的提升了性能。

而适应性自旋,是赋予了自旋一种学习能力,它并不固定自旋10次一下。他可以根据它前面线程的自旋情况,从而调整它的自旋,甚至是不经过自旋而直接挂起。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值