sychronized锁优化

本文深入解析Java锁优化机制,涵盖内核态与用户态概念、对象结构、CAS自旋及锁升级过程。从偏向锁、轻量级锁到重量级锁,详述锁优化策略及其在JVM中的实现细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

了解锁优化相关的知识,需要大致了解一以下概念:

  1. 内核态和用户态
  2. 对象结构
  3. cas自旋
  • 1 内核态和用户态 

       这两个概念是针对操作系统而言的,其实作为开人人员,可以不了解这些概念其实也可以敲出牛逼的程序。但是为了敲的更好还是了解下吧。操作系统是我们人类和冷冰冰的机器交互的中介,其实也可以把操作系统理解为一个软件,不过是这个软件上运行着许多其它软件,我们通过操作系统来操作硬件资源,各种程序就是各种命令,这样理解。那么问题来了,对于有些硬件,不是说用户你想操作就操作的,想操作就需要通过内核控制,打个比方,写个程序控制声卡,网卡,硬盘之类。如下图:

用户程序,比如我们编写的java程序。所谓用户态就是我个人理解就是你写的程序不需要从走内核申请资源操作权限之类的,所谓内核态就是你编写的程序要走内核程序,让内核程序老大哥给你分配资源和权限。那说了这么多,跟锁优化有什么鸟关系呐?接着看。

  • 2 对象结构

    当我们new出来对象后,这个对象不仅有它自身的那些结构信息,比如属性值,指针啥玩意儿,这些是必须的,不用想我们都能想到的。但是除了这些外,还有个对象头。所以这个对象的结构大致如下图所示:

我觉得这个图画的已经很明白了,除了对象本身,还有对象头信息。Markwork这块,8个字节,就是64位。这个对象头里面的结构。头信息里面结构如下图:

当进入对象的加锁方法时,没优化时候的锁是直接申请内核去拿到控制权,这个操作拿到的锁我们称为重量级锁,跟内核打交道的锁,稍微耗时一些。优化过后的锁是,当要加锁时,先不直接和内核打交道,先在对象头里标记下拿到锁了,然后就开始方法内的操作。这个过程我们叫做拿到的锁叫偏向锁。如果这时候再有别的线程也要进入这个对象的这个加锁方法的时候,来查看对象头的锁标记,一看已经有别的线程拿到锁了,就开始CAS自旋,等待锁释放,这时候偏向锁就升级为轻量级锁。如果十次后还没拿到锁,就升级为重量级锁,那就是去内核申请锁了。也有人称没有申请内核就拿到锁为无所,因为没和内核打交道嘛。偏向锁和轻量级锁也有人称为无锁。但是自旋竞争后没拿到锁后申请内核后拿到锁称为重量级锁,意思就是走内核拿到的锁。

这个锁升级的过程如下图:

  • 3 CAS

   步骤2中提到了CAS自旋,这个自旋就是走系统底层命令,等待对象头的锁信息释放后,就可以拿到锁。那个方法叫什么compareAndSweet方法,unsafe类的方法,最终走的是native方法。这个自旋的过程中,如果对象头的锁标记没释放,cas方法会自旋等待那个锁标识变为释放状态。cas再底层点的知识,就是走汇编指令了。

这个lock_if_mp 指令做的就是锁住cas要获取的那个变量的操作,也就是锁住了对象头标记,cas要拿到并改变这个锁标记只能等待lock指令结束。也就是说cas做的就是等待对象头上被别的线程占住的锁释放后拿到并改变锁标记为自己占有。拿10次发觉一直拿不到锁,就去内核申请锁了。这是cas这玩意儿的大概原理。要讲,东西太多,我们其实了解各大概这个思路就差不多了。我也翻看了很多资料,但是翻过来翻过去,感觉也都是讲的这么个意思。

    就一个线程拿锁的时候不走内核直接就拿到锁了叫偏向锁,轻度竞争升级为自旋锁,如果竞争的线程很多的时候,肯定会有线程自旋后拿不到锁,那锁就升级为重量级锁了。

   为什么需要偏向锁呐?因为其实我们jdk里有时候不需要上去拿锁就走内核要的。比如一些线程安全的类库,比如StringBuffer,Vetor,他们的方法都是加锁,但是我们平时使用这类类库时,基本不会说很多个线程去操作同一个对象,那么这时我们用它们的方法时候,虽然加了锁,但是优化后是加的偏向锁,没走内核,只是改了对象头的一个标识位而已。就算有多线程竞争,可能竞争也不会太多,经过轻度竞争cas自旋后也可以很快拿到锁,还是不走内核要控制权。这样,加锁和释放锁的效率就高了很多。所以虽然有时候一些追求极致效率的人会拿用StringBuffer这类类库来讲效率,但实话说,优化锁后的jdk,跟用不加锁的类库StringBuilder效率也差不多。但非要死磕那点效率,其实也没啥大的意义但是也有一定道理。就是这么回事。

      其实偏向锁升级为轻量级锁旋几次,jvm早起的版本是10次,还可以通过jvm参数调,但是后期好像说是废了这个参数,jvm自动调次数。自适应旋转次数,jvm根据线程竞争情况动态决定旋转多少次。这个自旋是占cpu资源的,所以线程竞争激烈的时候比较吃cpu资源。

   偏向锁也可能直接升级为重量级锁,那就是如果拿到偏向锁的线程执行的时间比较长或者有wait操作,那么竞争的锁就直接升级为重量级锁,毕竟如果很多个轻量级锁都自旋等待获取锁是个很耗cpu资源的事儿。直接升级为重量级锁就减轻了cpu的压力了。

   还有个匿名偏向锁:jvm的偏向锁默认是延迟打开的,4秒,为什么呐?因为jvm启动的时候其实有很多线程在启动的,会有竞争的,这些线程竞争锁的时候明明知道会产生cas自旋,那还偏向干啥,浪费资源,直接上轻量级锁了吧。这时候是直接越过偏向锁的,所以也叫匿名偏向锁。

      参与竞争的线程在自旋一定次数没拿到锁升级为重量级锁后的线程,是不占cpu资源的,因为重量级锁里有等待队列和竞争队列,如果锁被释放后,jvm会调度重量级锁的队列里的线程去获取锁。

    说到重量级锁,博主曾在面试的时候被问到过一个问题,就是创建锁的时候会创建什么对象?当时他给的提示是monitor对象,唉,也就是怪博主当时没研究到这一层,后来研究后才了解到,锁优化后升级到重量级锁后才会创建monitor对象,拿到锁后进入monitorenter指令,释放锁时候执行monitorexit指令。

其实说了这么多,所谓锁优化就是把上去就给对象加重量级锁,改成先加偏向锁,拿不到就升级为自旋的轻量级锁,再拿不到就升级后去内核申请的重量级锁。也就这么回事。如果面试遇到这样的问题,个人感觉能把这个道理说出来应该差不多了吧。不是说面特别高级的专家岗位的话。

内容概要:《机器人综合基础实践教程》(入门篇、提高篇)涵盖了机器人基础构建、编程控制、传感器应用等多个方面。教程从机械零件简介入手,逐步介绍主控板和编程环境的配置,随后通过一系列实验引导读者动手实践,包括驱动轮模块、双轮万向车、红外启动小车、带传动模块、履带机器人、红绿灯等实验。这些实验不仅帮助读者理解基本原理,还涉及高级应用如蓝牙电子温度计、语音识别、双轮小车平衡、蓝牙排爆机器人和WiFi视频排爆等。教程旨在培养读者的空间构型能力、编程技巧和综合调试能力,为机器人技术的实际应用打下坚实基础。 适用人群:具备一定编程基础和技术兴趣的学生、教师及爱好者,特别是对机器人技术感兴趣的初学者和中级学习者。 使用场景及目标:①帮助学生理解机器人基本原理,掌握机械零件组装和编程控制;②通过实际操作,提升编程和调试技能;③为机器人竞赛、项目开发和创新实践提供理论和实践指导;④培养创新思维和解决实际问题的能力。 其他说明:教程不仅提供详细的实验步骤和代码示例,还配有丰富的参考资料和光盘课件,确保学习者能够全面理解和掌握知识点。此外,教程强调实践操作的重要性,鼓励学习者通过动手实验加深理解,培养独立思考和解决问题的能力。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值