synchronized偏向锁 到 轻量级锁 的实验
JVM synchronized锁升级 实验(64位)
一. MarkWord图
- 32位虚拟机下:
- 64位虚拟机下:
由于我的机器是64位的, 因此后面的实验会参考 第二张图的内容做详解。
二、偏向锁延迟偏向 验证
HotSpot虚拟机在启动后开启偏向锁模式 默认在 4s后, 为了减少初始化时间,JVM默认延迟加载偏向锁。
参数开关
// 延迟开启偏向锁
-XX:BiasedLockingStartupDelay
// 禁止偏向锁
-XX:-UseBiasedLocking
实验代码:
public static void main(String[] args) throws InterruptedException {
System.out.println(ClassLayout.parseInstance(new A()).toPrintable());
Thread.sleep(4000);
System.out.println(ClassLayout.parseInstance(new A()).toPrintable());
}
实验结果:
实验结论:
默认JVM在启动4s后, 会为每个 new 的新对象头上 设置 偏向锁标志位。
此时仅仅是 偏向锁标志位是1, 但是其并不是真正处于偏向锁模式, 可以看作是一种 无锁的游离状态。
三、 批量重偏向锁 与 批量偏向锁撤销 实验
参数开关:
// 偏向锁批量重偏向阈值
-XX:BiasedLockingBulkRebiasThreshold 默认20
// 偏向锁批量撤销阈值
-XX:BiasedLockingBulkRevokeThreshold 默认40
测试代码:
package com.zzp.jvm;
import org.openjdk.jol.info.ClassLayout;
import javax.swing.plaf.synth.SynthOptionPaneUI;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
public class Test {
public static void main(String[] args) throws InterruptedException {
// 偏向锁模式延迟
Thread.sleep(5000);
List<A> listA = new ArrayList<>();
CountDownLatch cd1 = new CountDownLatch(1);
Thread t1 = new Thread(()->{
for (int i = 0; i < 40; i++) {
A a = new A();
synchronized (a){
listA.add(a);
}
}
System.out.println("t1 释放后的");
System.out.println(ClassLayout.parseInstance(listA.get(0)).toPrintable());
cd1.countDown();
});
t1.start();
CountDownLatch cd = new CountDownLatch(1);
Thread t2 = new Thread(() -> {
try {
cd1.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 40; i++) {
A a = listA.get(i);
synchronized (a) {
if (i == 18){
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
// 18-0 + 1 = 19
if (i == 19){
System.out.println("批量偏向锁阈值");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
}
cd.countDown();
});
t2.start();
CountDownLatch cd3 = new CountDownLatch(1);
Thread t3 = new Thread(() -> {
try {
cd.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 批量撤销阈值 38 - 0 + 1 = 39
for (int i = 19; i < 39; i++) {
A a = listA.get(i);
synchronized (a){
if (i == 19){
System.out.println("偏向锁撤销");
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
}
cd3.countDown();
});
t3.start();
cd3.await();
// 之后创建的 A对象, 都是无锁状态, 此无锁状态 若加锁 直接进入轻量级锁
A a = new A();
System.out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
测试结果:
万般皆下品,唯有读书高!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)