首页IT科技19斤盐先吃9斤再吃4斤一共吃了多少斤呢(19 Java内存模型与线程_JVM层面的锁优化)

19斤盐先吃9斤再吃4斤一共吃了多少斤呢(19 Java内存模型与线程_JVM层面的锁优化)

时间2025-06-14 20:43:24分类IT科技浏览3480
导读:1 锁优化历史 synchronized 从 JDK1.0到JDK1.5 ,效率低 JDK1.5到JDK1.6,JVM团队对synchronized进行深度优化,加入了:适应性自旋、锁消除、锁膨胀、轻量级锁、偏向锁 等优化技术 JDK1.5 开始,加入java.util.conc...

1 锁优化历史

synchronized 从 JDK1.0到JDK1.5            ,效率低 JDK1.5到JDK1.6                  ,JVM团队对synchronized进行深度优化      ,加入了:适应性自旋           、锁消除                  、锁膨胀      、轻量级锁        、偏向锁 等优化技术 JDK1.5 开始        ,加入java.util.concurrent                 ,提供API层面的轻量级锁应用

为什么优化synchronized?

互斥同步对性能最大的影响是阻塞的实现         ,挂起线程和恢复线程的操作都需要转入内核态中完成      ,这些操作给Java虚拟机的并发性能带来了很大的压力           。

2 自旋锁与自适应自旋

2.1 关于自旋锁

自旋锁历史进程:首次出现在JDK1.4.2                 ,但默认关闭(使用-XX:+UseSpinning参数开启)            ,在JDK6开始默认开启                  。

自旋锁实现逻辑:如果锁被其它线程占有   ,那么本线程不放弃处理器的执行时间                 ,并执行一个忙循环(自旋)               ,直至得到锁      。

自旋锁弊端:如果锁被占用的时间很长,那么自旋的线程只会白白消耗处理器资源              ,带来性能的浪费

自旋锁优化:

引入自旋次数:如果自旋超过了限定的次数仍然没有成功获得锁                  ,就应当使用传统的方式去挂起线程        。自旋次数的默认值是10次   ,可以启用参数-XX:PreBlockSpin来更改                 。(次数在JDK1.4.2已经实现) 引入了自适应自旋

2.1 自旋锁优化:自适应自旋

原来:所有线程的自旋时间统一的(PreBlockSpin配置值 * 单次自旋时间)

自适应自旋:自旋的时间不固定           ,JVM根据前一次在同一个锁上的自旋时间及锁的拥有者的状态

来决定         。

自适应自旋情形: 例如1:线程A                 、B                  ,锁L      。A先通过自旋获取锁      ,那么JVM认为B也能通过自旋获取到锁        ,随即给B分配自旋时间                 ,并且这个时间也是综合之前的自旋时间 例如2:锁L         ,线程A B C 通过自旋      ,都没有获取到锁                 ,那么JVM会对后续的线程省略自旋过程            ,以免浪费处理器资源

3 锁消除

定义:指虚拟机即时编译器在运行时   ,对一些代码要求同步                 ,但是对被检测到不可能存在共享数据竞争的锁进行消除                 。

判断依据:源于逃逸分析的数据支持               ,如果判断到一段代码中,在堆上的所有数据都不会逃逸出去被其他线程访问到              ,那就可以把它们当作栈上数据对待                  ,认为它们是线程私有的   ,同步加锁自然就无须再进行            。

举例:

一段看起来没有同步的代码:

public String concatString(String s1, String s2, String s3) { return s1 + s2 + s3; }

javac编译后           ,会变为以下同等代码:

public String concatString(String s1, String s2, String s3) { StringBuffer sb = new StringBuffer(); sb.append(s1); sb.append(s2); sb.append(s3); return sb.toString(); } //append()方法有synchronize修饰

分析:

jvm观察变量sb                  ,经过逃逸分析后会发现它的动态作用域被限制在concatString()方法内部   。可以采用无锁操作                 。

在解释执行时这里仍然会加锁      ,但在即时编译之后        ,这段代码就会忽略所有的同步措施而直接执行               。

锁消除总结:

JVM会进行逃逸分析                 ,符合条件的         ,在编译为机器码时      ,会消除所有同步措施

4 锁粗化

定义:假如一串零碎的操作都对同一个对象加锁                 ,JVM会把加锁同步的范围扩展(粗化)到整个操作序列的外部

举例:

例如上面concatString()方法            ,将锁扩展到第一个append()操作之前最后一个append()操作之后   ,这样只需加锁一次

5 轻量级锁

逻辑:无竞争的情况下使用CAS操作去消除同步使用的互斥量

轻量级锁提升性能的依据:“对于绝大部分的锁                 ,在整个同步周期内都是不存在竞争的           ”这一经验法则

过程分析:后续补充

6 偏向锁

逻辑:在无竞争的情况下把整个同步都消除掉               ,连CAS操作都不去做

“偏                  ”的理解:锁会偏向于第一个获得它的线程,如果在接下来的执行过程中              ,该锁一直没有被其他的线程获取                  ,则持有偏向锁的线程将永远不需要再进行同步。

过程分析:后续补充

声明:本站所有文章   ,如无特殊说明或标注           ,均为本站原创发布              。任何个人或组织                  ,在未征得本站同意时      ,禁止复制         、盗用      、采集                 、发布本站内容到任何网站            、书籍等各类媒体平台                  。如若本站内容侵犯了原著者的合法权益        ,可联系我们进行处理   。

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
默认网关不可用win7什么原因(默认网关不可用win7解决方法) 安卓手机解屏幕锁用什么软件好(手机解锁方法:8个顶级的 Android 手机解锁软件)