在另外的两篇文章中先后介绍了轻量级同步关键字volatile和重量级锁关键字synchronized,这两个关键字是Java语言中进行线程同步的基本方式(当然还有ReentrenLock等显式锁方式)。本文将就Java虚拟机针对同步原语做的一些锁优化进行简单的介绍,同时基于JDK 1.6将这些锁优化措施设置为默认值,对锁的获取流程进行图示。

锁优化

1、自旋锁与自适应自旋

我们知道,互斥同步时候,对性能影响最大的是阻塞的实现,挂起线程和恢复线程都需要陷入内核态去完成,而频繁的用户态内核态切换势必会造成频繁的上下文切换从而影响了性能,所以自旋锁就出现了,如果共享资源的占用时间不是很长的话,想要进入临界区的线程完全可以不放弃处理器的执行时间,只要执行一个忙循环即可。但是资源的占用时间也不是我们可以凭空想象的,所以我们可以通过-XX:PreBlockSpin参数来修改自旋次数,如果忙循环的循环次数大于了设置的自旋次数,那么还是执行原来的方式挂起线程。

2、锁消除

锁消除是指虚拟机在编译器运行时,对一些代码上要求同步,但是被检测到不可能存在共享数据竞争的锁进行消除。比如在判断一段代码中,堆上的数据都不会逃逸出去从而被其他的线程访问到,那么可以认为他们是线程私有的,同步加锁自然无须进行。

3、所粗化

我们熟悉的是减小锁的粒度如锁分解和锁分段等优化措施,但有的时候,如果一系列的连续操作对都对一个对象反复加锁和减锁,甚至枷锁操作是出现在循环体中的,那么即使没有线程竞争,频繁的进行互斥同步操作也会导致不必要的性能损耗。(注意:这项优化措施似乎在有了偏向锁和轻量级锁后就不太需要了---个人感觉)

4、轻量级锁

轻量级锁匙JDK 1.6之后新加入的新型锁机制,它的实现和后面的偏向锁的实现都需要Java对象头MarkWord信息的帮助

对象头中的MarkWord信息是可以复用的,复用的具体情况如上图所示。在代码进入同步块时,如果此对象没有被锁定(锁标志位“01”状态),虚拟机将在当前线程的栈帧中建立一个名为锁记录(Lock Record)的空间,用于存储锁对象目前的MarkWord拷贝(官方把这份拷贝加了一个Displaced前缀,即Displaced Mark Word)

然后,虚拟机将使用CAS操作尝试将对象的Mark Word更新为指向Lock Record的指针,如果这个更新成功了,那么这个线程就拥有了该对象的锁,并且对象Mark Word的锁标志位(Mark Word的最后2bit)将转变为“00”,即表示此对象处于轻量级锁定状态

如果更新失败了,虚拟机首先会检查对象的Mark Word是否指向当前线程的栈帧,如果只说明了当前线程已经拥有了这个对象的锁,那就可以直接进入同步块执行,否则则说明这个锁对象已经被其他线程抢占了。如果有两个不同的线程抢占同一个锁,那么轻量级锁就会膨胀为重量级锁(互斥同步)

5、偏向锁

偏向锁的目的是消除数据在无竞争情况下的同步原语,进一步提高程序的运行性能。轻量级锁匙在无竞争的情况下使用CAS操作去消除同步使用的互斥量,那偏向锁就是在无竞争的情况下把整个同步都消除掉,连CAS也不要了。它的实现原理和轻量级锁一样,也是和对象头的Mark Word相关。

结合所有的锁优化步骤,那么代码执行锁获取操作的流程如下图所示

参考资料:《深入理解Java虚拟机》---周志明

JAVA并发之锁获取步骤及锁优化的更多相关文章

  1. Java并发之彻底搞懂偏向锁升级为轻量级锁

    网上有许多讲偏向锁,轻量级锁的文章,但对偏向锁如何升级讲的不够明白,有些文章还相互矛盾,经过对jvm源码(biasedLocking.cpp)的仔细分析和追踪,基本升级过程有了一个清晰的过程,现将升级 ...

  2. Java多线程(五) —— 线程并发库之锁机制

    参考文献: http://www.blogjava.net/xylz/archive/2010/07/08/325587.html 一.Lock与ReentrantLock 前面的章节主要谈谈原子操作 ...

  3. JVM锁简介:偏向锁、轻量级锁和重量级锁

    转自:https://www.aimoon.site/blog/2018/05/21/biased-locking/ 比较复杂,简略见另一篇:https://www.cnblogs.com/twohe ...

  4. 001-多线程-锁-架构【同步锁、JUC锁】

    一.概述 Java中的锁,可以分为"同步锁"和"JUC包中的锁". 1.1.同步锁 即通过synchronized关键字来进行同步,实现对竞争资源的互斥访问的锁 ...

  5. java并发之线程同步(synchronized和锁机制)

    使用synchronized实现同步方法 使用非依赖属性实现同步 在同步块中使用条件(wait(),notify(),notifyAll()) 使用锁实现同步 使用读写锁实现同步数据访问 修改锁的公平 ...

  6. Java并发之显式锁和隐式锁的区别

    Java并发之显式锁和隐式锁的区别 在面试的过程中有可能会问到:在Java并发编程中,锁有两种实现:使用隐式锁和使用显示锁分别是什么?两者的区别是什么?所谓的显式锁和隐式锁的区别也就是说说Synchr ...

  7. Java并发之锁升级:无锁->偏向锁->轻量级锁->重量级锁

    Java并发之锁升级:无锁->偏向锁->轻量级锁->重量级锁 对象头markword 在lock_bits为01的大前提下,只有当是否偏向锁位值为1的时候,才表明当前对象处于偏向锁定 ...

  8. 转 Java并发之锁的升级

    说明:本文大部分内容来自<并发编程的艺术>,再加上自己网络整理和理解 以下内容来自<java并发编程的艺术>作者:方鹏飞 魏鹏 程晓明 在多线程并发编程中synchronize ...

  9. Java并发之(3):锁

    锁是并发编程中的重要概念,用来控制多个线程对同一资源的并发访问,在支持并发的编程语言中都有体现,比如c++ python等.本文主要讲解Java中的锁,或者说是重入锁.之所以这么说是因为在Java中, ...

随机推荐

  1. 如何学习Python的一些总结

    https://mp.weixin.qq.com/s/w0NoDiYfvtTy8N3BVoIVpw 为什么选择Python 经常会有同学问我为什么选择Python.我很喜欢这门语言,因为它的简洁灵活, ...

  2. Element-ui学习笔记3--Form表单(三)

    InputNumber <el-input-number v-model="num" @change="handleChange" :min=" ...

  3. 机器学习降维方法概括, LASSO参数缩减、主成分分析PCA、小波分析、线性判别LDA、拉普拉斯映射、深度学习SparseAutoEncoder、矩阵奇异值分解SVD、LLE局部线性嵌入、Isomap等距映射

    机器学习降维方法概括   版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/u014772862/article/details/52335970 最近 ...

  4. C++调用Lua编程环境搭建及测试代码示例

    C++调用Lua编程环境搭建及测试代码示例 摘要:测试环境是VS2005+LuaForWindows_v5.1.4-45.exe+WIN7 1.安装lua开发环境LuaForWindows_v5.1. ...

  5. H3C开启Ssh

    [H3C]ssh server enable                       //开启SSH服务 [H3C]user-interface vty 0 4 [H3C-ui-vty0-4]au ...

  6. Linux 字节序

    小心不要假设字节序. PC 存储多字节值是低字节为先(小端为先, 因此是小端), 一些高 级的平台以另一种方式(大端)工作. 任何可能的时候, 你的代码应当这样来编写, 它不在 乎它操作的数据的字节序 ...

  7. 2018-8-10-C#-写系统日志

    title author date CreateTime categories C# 写系统日志 lindexi 2018-08-10 19:16:53 +0800 2018-2-13 17:23:3 ...

  8. 【hdu 1850】Being a Good Boy in Spring Festival

    Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s) ...

  9. LuoguP2765 魔术球问题

    LuoguP2765 魔术球问题 首先,很难看出来这是一道网络流题.但是因为在网络流24题中,所以还是用网络流的思路 首先考虑完全平方数的限制. 如果\(i,j\)满足\(i < j\) 且 $ ...

  10. 【矩阵乘法优化dp】[Codeforces 621E] Wet Shark and Blocks

    http://codeforces.com/problemset/problem/621/E E. Wet Shark and Blocks time limit per test 2 seconds ...