Synchronized以及锁的状态

Java对象头

以Hotspot虚拟机为例,对象头包括标记字段Mark Word和类型指针Klass Pointer。
Mark Word:默认存储对象的HashCode,分代年龄、锁标志位信息。这些信息与对象自身定义无关。
Klass Point:对象指向它的类元数据的指针,虚拟机通过该指针来确定这个对象是哪个类的实例。
图 1 32bit虚拟机
图 2 64bit虚拟机

Monitor

synchronized获取对象的监视器锁,如果该监视器锁计数器为0表示没有被持有,则该线程获取锁(monitorenter),并将计数器加1;当该线程再次获取同一个锁时(monitorenter),计数器加1;该线程释放锁时(monitorexit),计数器减1;当计数器为0时,锁被真正释放。——synchronized为可重入锁。
synchronized通过对象内部的监视器锁Monitor实现,其本质是依赖底层操作系统的互斥锁实现的。会导致线程阻塞、引起线程间的切换,相对自旋锁来说资源消耗大,因此互斥锁又是重量级锁。
Java6为了减少获得锁和释放锁带来的性能损耗,引入了偏向锁和轻量级锁。默认开启,可以通过-XX:-UseBiasedLocking=false来禁用偏向锁。
monitor锁状态依照级别从低到高,有:无锁、偏向锁、轻量级锁、重量级锁。随着锁的竞争,可以单向升级锁的级别。

无锁——没有对资源进行锁定,所有线程都可以对同一资源进行访问,但只有一个线程能够成功修改资源。
其特点是在循环内进行修改操作,线程会不断尝试修改共享资源,直到成功后退出。像CAS就是无锁的实现。线程lock的过程中不断获取共享资源(如TicketLock中的callNum),直到达到某种条件。

偏向锁——大多数情况下,锁不仅存在多线程竞争,还存在锁由同一线程多次获得的情况。偏向锁就是解决在一个线程执行同步时提高性能。
偏向锁的Mark Word种保存了线程Id和epoch(可以作为检测偏向锁有效性的时间戳),当一个线程获取锁时,其id会被记录到对象头中;等到下一次线程再次获取锁时,只需要简单判断下对象头即可。
偏向锁的获取过程:
① 访问Mark Word中锁标志位为01,偏向锁标志位为1,确认可偏向状态;
② 判断当前线程id与对象头中存储的线程id是否一致,如果不一致进入step③;否则进入step⑤
③ 通过CAS操作来竞争获取锁,若竞争成功,改写对象头中的线程id,进入step⑤,否则执行step④;
④ 若CAS获取偏向锁失败,则表示有竞争(其他线程曾获取过偏向锁,但是不会主动释放)。当到达全局安全点时,会首先暂停拥有偏向锁的线程,然后检查持有偏向锁的线程是否存活;如果线程不存活则将对象头置为无锁状态,重新偏向新的线程;如果线程存活,判断该线程是否继续持有锁如果需要继续持有,则撤销偏向锁后升级为轻量级锁状态,此时轻量级锁由原持有偏向锁的线程持有,继续执行其同步代码块,而正在竞争的线程进入自旋状态等待获取该轻量级锁;如果线程不再需要持有锁,则将对象头置为无锁状态,重新偏向新的线程。
⑤ 获得锁,执行同步代码块。
偏向锁释放过程:
偏向锁在遇到其他线程竞争时,持有偏向锁的线程才会释放锁,线程不会主动释放偏向锁。偏向锁的撤销要等到全局安全点(该时间点上没有字节码在执行),会首先暂停拥有偏向锁的线程,判断锁是否处于被锁定状态,撤销偏向锁后恢复到无锁或轻量级锁状态。

轻量级锁——当前锁是偏向锁时,被另外的线程访问,该偏向锁就会升级成轻量级锁,其他线程通过自旋的形式尝试获取锁,不会阻塞,从而提高性能。
线程在获取轻量级锁后,对象头中的锁指针会被设置为指向自己。这样,当两个线程竞争轻量级锁时,都尝试将对象头中的指针指向自己,利用CAS原理,只会有一个设置成功,另一个进入自旋等待。
自旋消耗CPU资源,因此会有一个自旋阈值,当自旋次数超过该阈值或者又有其他线程也参与竞争该轻量级锁时,轻量级锁升级成重量级锁,阻塞其他线程,防止自旋空转。

重量级锁——互斥锁,Java6之前synchronized的实现

总结

目前synchronized的加锁性能得到提升,源自于偏向锁和轻量级锁的引入,利用了CAS原理及实现。偏向锁用在基本没有线程竞争的场景,提高单一线程重入锁的性能;轻量级锁在偏向锁存在竞争时升级,适用于少量线程竞争锁并且持有锁时间较短(乐观锁的适用场景)时;重量级锁适用于很多线程竞争且锁持有时间较长的场景(悲观锁)。
由于加锁解锁也需要消耗资源,如果存在一系列加解锁操作,会带来性能损耗,此时可以将这些加解锁操作合并起来,扩展成一个更大范围的锁——锁的粗化。
JVM在JIT编译时,也会通过上下文扫描,逃逸分析去除不可能存在共享资源竞争的锁——锁的消除。

参考:Java并发——Synchronized关键字和锁升级,详细分析偏向锁和轻量级锁的升级

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值