ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

sychronized 锁升级

2021-10-26 12:04:24  阅读:198  来源: 互联网

标签:无锁 对象 升级 获取 线程 偏向 sychronized 轻量级


sychronize有几种锁

sychronize
1.6之前,只存在重量级锁,也就是一个线程拿到锁之后,其他没有拿到锁的线程只能阻塞。
1.6之后,新加了偏向锁和轻量级锁(自旋锁)。

无锁

无锁是指没有对资源进行锁定,所有的线程都能访问并修改同一个资源,但同时只有一个线程能修改成功。

也就是说,理想情况下,所有获取锁的线程都能够在第一次尝试的时候就成功,也就是没有真正发生竞争,此时,sychronized不会真正的加锁。
实际上不是这样。当对象刚被new出来的时候,没有线程进行访问,此时是无锁状态,一旦有线程来访问,其实第一个线程会加偏向锁。或者偏向锁撤销 对象头中的mark word 是空的时候 也是无锁状态。

也就是不存在多个线程访问,互相不冲突,大家维持友好的无锁状态这种事。

偏向锁

偏向锁是指当一段同步代码一直被同一个线程所访问时,即不存在多个线程的竞争时,那么该线程在后续访问时便会自动获得锁,从而降低获取锁带来的消耗,即提高性能。

也就是说,此时也没有发生真正的竞争,可以理解为不存在第二个线程来获取锁,当对象被第一个线程访问,当锁对象第一次被线程获取的时候,虚拟机会把对象头中的标志位设为01、把偏向模式设置为1,表示进入偏向模式。同时使用CAS操作把获取到这个锁的线程的ID记录在对象的Mark Word中,如果CAS操作成功,持有偏向锁的线程以后每次进入这个锁相关的同步块时。虚拟机都可以不再进行任何同步操作(例如加锁、解锁以及对Mark Word的更新操作等)。

轻量级锁/自旋锁

轻量级锁是指当锁是偏向锁的时候,却被另外的线程所访问,此时偏向锁就会升级为轻量级锁,其他线程会通过自旋(关于自旋的介绍见文末)的形式尝试获取锁,线程不会阻塞,从而提高性能。

轻量级锁的获取主要由两种情况:① 当关闭偏向锁功能时;② 由于多个线程竞争偏向锁导致偏向锁升级为轻量级锁。

也就是说,一旦发生了两个线程同时获取一把锁的情况,偏向锁就不合适了,会升级成轻量级锁,之所以称之为“轻量”,是因为其他没有获取到锁的线程并不会进入阻塞状态,而是会进入“自旋”,其实就是进入循环,循环内会尝试继续获取锁。

可以看一下偏向锁到轻量级锁的升级过程

  1. 在代码即将进入同步块的时候,如果此同步对象没有被锁定(锁标志位为01状态),虚拟机首先将在当前线程的栈帧中建立一个名为锁记录的空间,用于存储锁对象目前的Mark Word拷贝(官方为这份拷贝加了个前缀Displaced)。
  2. 然后虚拟机将使用CAS操作尝试把对象的Mark Word更新为指向Lock Record的指针。如果这个更新动作成功了,即代表该线程拥有了这个对象的锁,并且对象Mark Word的锁标志位(Mark Word的最后两个比特)将转变为00,表示此对象处于轻量级锁定状态。
  3. 如果这个操作失败了,那就意味着至少存在一条线程与当前线程竞争获取该对象的锁。虚拟机首先会检查对象的Mark Word是否指向当前线程的栈帧。如果是,说明当前线程已经拥有了这个对象的锁,那直接进入同步块继续执行就可以了,否则就说明这个锁对象已经被其他线程抢占了。当前线程会进行自旋。
  4. 如果出现两条以上的线程争用同一个锁,或者当前线程自旋失败(尝试到一定次数,默认10次)的情况,那轻量级锁就不再有效,必须要膨胀为重量级锁,锁标志的状态值变为10,此时Mark Word中存储的就是指向重量级锁监视器ObjectMonitor(互斥量)的指针,后面等待锁的线程也必须进入阻塞状态。

重量级锁

重量级锁是指当有一个线程获取锁之后,其余所有等待获取该锁的线程都会处于阻塞状态。

重量级锁通过对象内部的监视器(monitor)实现,而其中 monitor 的本质是依赖于底层操作系统的 Mutex Lock 实现,操作系统实现线程之间的切换需要从用户态切换到内核态,切换成本非常高。

简而言之,重量级锁和我们平常使用的lock区别不大,一旦有一个线程获取到了锁,其他没有获取到锁的线程都只能进入阻塞状态排队。

锁升级状态

所以,锁升级有两条线路:

  1. 偏向锁打开的情况下,当对象被new出来,此时是无锁,当第一个线程来访问并获取锁的时候,加一个偏向锁,如果在第一个线程持有偏向锁期间,有其他的线程也来获取锁,那么此时升级为轻量级锁,如果竞争比较激烈,比如自旋的线程尝试多次仍旧获取不到锁,就有可能升级为重量级锁。也就是无锁→偏向锁→轻量级锁→重量级锁
  2. 偏向锁关闭的情况下,当对象被new出来,此时是无锁,当第一个线程来访问,直接就加轻量级锁,如果竞争比较激烈,比如自旋的线程尝试多次仍旧获取不到锁,就有可能升级为重量级锁。也就是无锁→轻量级锁→重量级锁

总结

以上是我的思考,有不对的地方欢迎大家指出(我觉得肯定有不对的地方,可是现阶段我就是这么理解的,希望大家积极指出),感谢大家帮助我提高。

参考

synchronized与锁升级(示例代码)
synchronized四种锁状态的升级

标签:无锁,对象,升级,获取,线程,偏向,sychronized,轻量级
来源: https://www.cnblogs.com/awada/p/15465061.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有