网站怎么被百度收录,品牌网络推广,大连网站建设领超最好,湛江网站建设制作价格1.锁膨胀 #xff08;就是锁升级#xff09;
我们先来回顾一下锁膨胀对 synchronized 性能的影响#xff0c;所谓的锁膨胀是指 synchronized 从无锁升级到偏向锁#xff0c;再到轻量级锁#xff0c;最后到重量级锁的过程#xff0c;它叫锁膨胀也叫锁升级。 JDK 1.6 之前…1.锁膨胀 就是锁升级
我们先来回顾一下锁膨胀对 synchronized 性能的影响所谓的锁膨胀是指 synchronized 从无锁升级到偏向锁再到轻量级锁最后到重量级锁的过程它叫锁膨胀也叫锁升级。 JDK 1.6 之前synchronized 是重量级锁也就是说 synchronized 在释放和获取锁时都会从用户态转换成内核态而转换的效率是比较低的。但有了锁膨胀机制之后synchronized 的状态就多了无锁、偏向锁以及轻量级锁了这时候在进行并发操作时大部分的场景都不需要用户态到内核态的转换了这样就大幅的提升了 synchronized 的性能。 2.锁消除
很多人都了解 synchronized 中锁膨胀的机制但对接下来的 3 项优化却知之甚少这样会在面试中错失良机那么我们本文就把这 3 项优化单独拎出来讲一下吧。
锁消除指的是在某些情况下JVM 虚拟机如果检测不到某段代码被共享和竞争的可能性就会将这段代码所属的同步锁消除掉从而到底提高程序性能的目的。
锁消除的依据是逃逸分析的数据支持如 StringBuffer 的 append() 方法或 Vector 的 add() 方法在很多情况下是可以进行锁消除的比如以下这段代码
public String method() {
StringBuffer sb new StringBuffer();
for (int i 0; i 10; i) {
sb.append(i: i);
}
return sb.toString();
}
以上代码经过编译之后的字节码如下 从上述结果可以看出之前我们写的线程安全的加锁的 StringBuffer 对象在生成字节码之后就被替换成了不加锁不安全的 StringBuilder 对象了原因是 StringBuffer 的变量属于一个局部变量并且不会从该方法中逃逸出去所以此时我们就可以使用锁消除不加锁来加速程序的运行。 3.锁粗化
锁粗化是指将多个连续的加锁、解锁操作连接在一起扩展成一个范围更大的锁。
我只听说锁“细化”可以提高程序的执行效率也就是将锁的范围尽可能缩小这样在锁竞争时等待获取锁的线程才能更早的获取锁从而提高程序的运行效率但锁粗化是如何提高性能的呢
没错锁细化的观点在大多数情况下都是成立了但是一系列连续加锁和解锁的操作也会导致不必要的性能开销从而影响程序的执行效率比如这段代码
public String method() {
StringBuilder sb new StringBuilder();
for (int i 0; i 10; i) {
// 伪代码加锁操作
sb.append( i);
// 伪代码解锁操作
}
return sb.toString();
}
这里我们不考虑编译器优化的情况如果在 for 循环中定义锁那么锁的范围很小但每次 for 循环都需要进行加锁和释放锁的操作性能是很低的但如果我们直接在 for 循环的外层加一把锁那么对于同一个对象操作这段代码的性能就会提高很多如下伪代码所示
public String method() {
StringBuilder sb new StringBuilder();
// 伪代码加锁操作
for (int i 0; i 10; i) {
sb.append( i);
}
// 伪代码解锁操作
return sb.toString();
}
锁粗化的作用如果检测到同一个对象执行了连续的加锁和解锁的操作则会将这一系列操作合并成一个更大的锁从而提升程序的执行效率。 4.自适应自旋锁
自旋锁是指通过自身循环尝试获取锁的一种方式伪代码实现如下
// 尝试获取锁
while(!isLock()){}
自旋锁优点在于它避免一些线程的挂起和恢复操作因为挂起线程和恢复线程都需要从用户态转入内核态这个过程是比较慢的所以通过自旋的方式可以一定程度上避免线程挂起和恢复所造成的性能开销。
但是如果长时间自旋还获取不到锁那么也会造成一定的资源浪费所以我们通常会给自旋设置一个固定的值来避免一直自旋的性能开销。然而对于 synchronized 关键字来说它的自旋锁更加的“智能”synchronized 中的自旋锁是自适应自旋锁这就好比之前一直开的手动挡的三轮车而经过了 JDK 1.6 的优化之后我们的这部“车”一下子变成自动挡的兰博基尼了。 自适应自旋锁是指线程自旋的次数不再是固定的值而是一个动态改变的值这个值会根据前一次自旋获取锁的状态来决定此次自旋的次数。比如上一次通过自旋成功获取到了锁那么这次通过自旋也有可能会获取到锁所以这次自旋的次数就会增多一些而如果上一次通过自旋没有成功获取到锁那么这次自旋可能也获取不到锁所以为了避免资源的浪费就会少循环或者不循环以提高程序的执行效率。简单来说如果线程自旋成功了则下次自旋的次数会增多如果失败下次自旋的次数会减少。 总结
本文我们介绍了 4 种优化 synchronized 的方案其中锁膨胀和自适应自旋锁是 synchronized 关键字自身的优化实现而锁消除和锁粗化是 JVM 虚拟机对 synchronized 提供的优化方案这些优化方案最终使得 synchronized 的性能得到了大幅的提升也让它在并发编程中占据了一席之地。 知识来源
百度安全验证