Java编程——从JVM的角度分析Synchronize 关键字原理
众所周知 Synchronize 关键字是解决并发问题常用解决方案,有以下三种使用方式:
1、同步普通方法,锁的是当前对象。
2、同步静态方法,锁的是当前 Class 对象。
3、同步块,锁的是 {} 中的对象。
实现原理: JVM 是通过进入、退出对象监视器( Monitor )来实现对方法、同步块的同步的。
具体实现是在编译之后在同步方法调用前加入一个 monitor.enter 指令,在退出方法和异常处插入 monitor.exit 的指令。
其本质就是对一个对象监视器( Monitor )进行获取,而这个获取过程具有排他性从而达到了同一时刻只能一个线程访问的目的。
而对于没有获取到锁的线程将会阻塞到方法入口处,直到获取锁的线程 monitor.exit 之后才能尝试继续获取锁。
流程图如下:
通过一段代码来演示:
使用 javap -c Synchronize 可以查看编译之后的具体信息。
可以看到在同步块的入口和出口分别有 monitorenter,monitorexit 指令。
锁优化
synchronize 很多都称之为重量锁,JDK1.6 中对 synchronize 进行了各种优化,为了能减少获取和释放锁带来的消耗引入了偏向锁和轻量锁。
轻量锁
当代码进入同步块时,如果同步对象为无锁状态时,当前线程会在栈帧中创建一个锁记录(Lock Record)区域,同时将锁对象的对象头中 Mark Word 拷贝到锁记录中,再尝试使用 CAS 将 Mark Word 更新为指向锁记录的指针。
如果更新成功,当前线程就获得了锁。
如果更新失败 JVM 会先检查锁对象的 Mark Word 是否指向当前线程的锁记录。
如果是则说明当前线程拥有锁对象的锁,可以直接进入同步块。
不是则说明有其他线程抢占了锁,如果存在多个线程同时竞争一把锁,轻量锁就会膨胀为重量锁。
解锁
轻量锁的解锁过程也是利用 CAS 来实现的,会尝试锁记录替换回锁对象的 Mark Word 。如果替换成功则说明整个同步操作完成,失败则说明有其他线程尝试获取锁,这时就会唤醒被挂起的线程(此时已经膨胀为重量锁)
轻量锁能提升性能的原因是:
认为大多数锁在整个同步周期都不存在竞争,所以使用 CAS 比使用互斥开销更少。但如果锁竞争激烈,轻量锁就不但有互斥的开销,还有 CAS 的开销,甚至比重量锁更慢。
偏向锁
为了进一步的降低获取锁的代价,JDK1.6 之后还引入了偏向锁。
偏向锁的特征是:锁不存在多线程竞争,并且应由一个线程多次获得锁。
当线程访问同步块时,会使用 CAS 将线程 ID 更新到锁对象的 Mark Word 中,如果更新成功则获得偏向锁,并且之后每次进入这个对象锁相关的同步块时都不需要再次获取锁了。
释放锁
当有另外一个线程获取这个锁时,持有偏向锁的线程就会释放锁,释放时会等待全局安全点(这一时刻没有字节码运行),接着会暂停拥有偏向锁的线程,根据锁对象目前是否被锁来判定将对象头中的 Mark Word 设置为无锁或者是轻量锁状态。
偏向锁可以提高带有同步却没有竞争的程序性能,但如果程序中大多数锁都存在竞争时,那偏向锁就起不到太大作用。可以使用 -XX:-userBiasedLocking=false 来关闭偏向锁,并默认进入轻量锁。
其他优化
适应性自旋
在使用 CAS 时,如果操作失败,CAS 会自旋再次尝试。由于自旋是需要消耗 CPU 资源的,所以如果长期自旋就白白浪费了CPU。JDK1.6加入了适应性自旋:
如果某个锁自旋很少成功获得,那么下一次就会减少自旋。
欢迎工作一到五年的Java工程师朋友们加入Java架构开发:468947140
点击链接加入群聊【Java-BATJ企业级资深架构】:https://jq.qq.com/?_wv=1027&k=5zMN6JB
本群提供免费的学习指导 架构资料 以及免费的解答
不懂得问题都可以在本群提出来 之后还会有职业生涯规划以及面试指导
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
程序员被聘用的13个开发技能
1.JavaScript 这些日子,开发人员掌握JavaScript总不会错。JavaScript能力是目前为止被高层执行人员和招聘人员誉为最频繁的追捧技能。JavaScript已被证明是当今市场中高度可移植和宝贵的技能。 2.了解大数据 大数据项目相较于去年继续扩大,而且在这几年里也没有放缓的迹象。开发人员必须有全面的(商业智能)和分析产品,机器学习工具和其他可以转移、存储和汇总大量数据解决方案的知识。只有这样,他们才能帮助他们的公司存储,交互和分析大数据,以便于做出更好的业务决策。 3.掌握全栈 现在许多的顶级公司都在寻求可轻松应对各种技术和平台的全栈开发人员。 4.涉及开发运营 炽热的就业前景并不是考虑在简历中添加开发运营经验的唯一原因:开发运营实践会让你成为一个更优秀的开发人员和一个更有价值的合作者。 开发运营实践还可以提高团队凝聚力和业务敏捷性。这是一种能让企业加速领先一步的边缘技能。 5.多样化 相比前几年,现在的企业希望寻找更丰富的技能。Java和C#仍然占据市场部分份额,但是当你去看那些在上次经济衰退之后成立的公司,那么你将看到各种类型的语言需求:Ruby on Rai...
- 下一篇
IntelliJ IDEA最好的Java开发工具
一直以来,笔者从事Java开发使用的都是Myeclipse、Eclipse工具,因为Eclipse的开源免费加上之前其基金会每年都会安排同步发布新版本,其在05年之后逐步成为Java IDE界的扛把子,但令人失望的是自15年发布代号为Mars版本之后至今都没有新的核心版本了。然而这几年随着软件应用的飞速发展,程序员对开发效率及编程体验的追求也越来越高了,笔者亦不例外。 IntelliJ IDEA自2001年发布以来一直都是需要商业付费的,但由于其最近几年推出来了开源免费社区版,这让其备受关注,再次迎来了快速发展的时刻,如今越来越多的程序员开始尝试使用IntelliJ IDEA作为日常开发工具。笔者现在使用的笔记本是MacBook Pro 17版,因为Eclipse在最新macOS High Sierra操作系统下的表现可谓用糟糕二字来形容,经常出现卡死、快捷操作闪退等问题,所以笔者一直以来都在想找到替代工具,于是乎IntelliJ IDEA惊艳入眼。笔者也是最近才开始接触这个IDE,就这几日的体验来说真的是一级棒。 既然你已经阅读至此,那就随笔者来一探IntelliJ IDEA究竟吧。...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- MySQL8.0.19开启GTID主从同步CentOS8
- Hadoop3单机部署,实现最简伪集群
- CentOS8编译安装MySQL8.0.19
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- Windows10,CentOS7,CentOS8安装MongoDB4.0.16
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- SpringBoot2整合Thymeleaf,官方推荐html解决方案
- Eclipse初始化配置,告别卡顿、闪退、编译时间过长
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- Mario游戏-低调大师作品