Java偏向锁、轻量级锁、重量级锁过程详解

本文详细介绍了Java中的锁优化机制,包括偏向锁、轻量级锁和重量级锁。偏向锁适用于单线程访问,通过记录线程ID减少开销;轻量级锁采用CAS和自旋避免线程阻塞,适合线程交替进入同步代码;而重量级锁在高竞争场景下使用,依赖操作系统互斥量,可能导致线程阻塞。理解这些锁机制有助于提升Java多线程程序的性能。
摘要由CSDN通过智能技术生成

偏向锁、轻量级锁、重量级锁

因为早期Java版本的synchronized底层实现采取的是操作系统的互斥量,线程阻塞和唤醒的代价很大,性能较低,因此Java尝试在多线程竞争不那么激烈的情况下,降低锁的开销。

1、偏向锁

偏向锁适用于只有一个线程进入同步代码的情况

偏向锁会偏向于获得偏向锁的线程,它会在对象头的markword存储当前获取偏向锁的线程ID,当该线程下次获取锁的时候无需额外的操作只需要判断一下当前线程是否指向自己,如果指向自己则成功获得锁,否则进行偏向锁的撤销(偏向锁的撤销会产生两种结果:1、另一个线程成功获得偏向锁.2、偏向锁升级为轻量级锁)

偏向锁加锁过程

如果当前对象是无锁可偏向状态,那么会采用CAS算法将锁对象的markword中写入自己的线程ID,如果写入成功,则成功获取锁,否则发生了竞争,进行偏向锁的撤销流程。

偏向锁的撤销

首先jvm会暂停所有线程的执行,然后检查当前对象头中记录的线程ID所指向的线程是否存活、或者是否执行完同步代码,如果执行完了,说明此时偏向锁处于无锁状态,将会重偏向给发起偏向锁撤销的那个线程。如果记录的线程ID仍然存活着,那么将偏向锁升级为轻量级锁。

2、轻量级锁

轻量级锁适用于线程交替进入同步代码区的情况

轻量级锁基本原理是采用CAS+自旋的方式避免线程阻塞和唤醒的开销。

轻量级锁的加锁过程

首先如果发现对象处于无锁状态,那么会在当前栈帧中开辟一块空间,保存对象markword的副本,然后通过CAS算法将对象头的Markword设置为指向该副本的指针,如果设置成功,则说明成功获取锁,如果获取失败,则自旋等待获取锁(当自旋多次依旧没有获取到锁时。会将轻量级锁升级为重量级锁(设置对象的锁标记为重量级锁))。

轻量级锁的释放

使用CAS算法将栈帧中保存的markword副本放回对象头中,如果成功则加锁失败,如果失败了,那么说明在持有锁的过程中锁被升级为了重量级锁,因此会释放锁,并且唤醒阻塞等待的线程。

3、重量级锁

重量级锁适用于线程竞争激烈的场景

采用操作系统互斥量实现,当发现对象无锁时,会获取锁。如果获取锁失败或者对象本身就处于锁定状态,会进入阻塞状态,等待线程唤醒。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值