JVM 内置锁 synchronized 关键字,偏向锁优化中的批量重偏向和批量撤销(下)

简介: JVM 内置锁 synchronized 关键字,偏向锁优化中的批量重偏向和批量撤销

批量偏向锁撤销


当撤销偏向锁的阈值超过 40 次过后, jvm  会认为不该偏向,于是整个类的所有对象都会变成不可偏向,新创建的对象也不可偏向。 注意:  对于统计批量撤销有个参数:-XX:BiasedLockingDecayTime=25000ms范围内没有达到 40 次,撤销次数清 0 ,重新记时


public class B1 {
    public static void main(String[] args) throws Exception {
        Thread.sleep(5000);
        List<A> listA = new ArrayList<>();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i <100 ; i++) {
                A a = new A();
                synchronized (a){
                    listA.add(a);
                }
            }
            try {
                Thread.sleep(100000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t1.start();
        Thread.sleep(3000);
        Thread t2 = new Thread(() -> {
            //这里循环了40次。达到了批量撤销的阈值
            for (int i = 0; i < 40; i++) {
                A a =listA.get(i);
                synchronized (a){
                }
            }
            try {
                Thread.sleep(10000000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t2.start();
        Thread.sleep(3000);
        System.out.println("打印list中第11个对象的对象头:");
        System.out.println((ClassLayout.parseInstance(listA.get(10)).toPrintable()));
        System.out.println("打印list中第26个对象的对象头:");
        System.out.println((ClassLayout.parseInstance(listA.get(25)).toPrintable()));
        System.out.println("打印list中第90个对象的对象头:");
        System.out.println((ClassLayout.parseInstance(listA.get(89)).toPrintable()));
        Thread t3 = new Thread(() -> {
            for (int i = 20; i < 40; i++) {
                A a =listA.get(i);
                synchronized (a){
                    if(i==20||i==22){
                        System.out.println("thread3 第"+ i + "次");
                        System.out.println((ClassLayout.parseInstance(a).toPrintable()));
                    }
                }
            }
        });
        t3.start();
        Thread.sleep(10000);
        System.out.println("重新输出新实例A");
        System.out.println((ClassLayout.parseInstance(new A()).toPrintable()));
    }
}


看看输出结果,这部分和上面的批量偏向有些不同。重点关注线程 id

前 20 个对象并没有触发批量重偏向机制,线程 t2 释放锁之后,变成无锁状态;

第 20 - 40 个对象,触发了批量重偏向机制,对象为偏向锁状态,偏向线程 t2, 线程 t2 的 id 为 -1005618939


第 41 个对象之后,也没有触发了批量重偏向机制,对象依然偏向线程 t1 , 线程 t1  的 id 是  -1039208443


image.png


t3 线程开始进行锁的竞争,因为已经到到批量撤销的阈值,且对象  listA.get(20) 和 listA.get(22) 已经进行了锁的重偏向了,所以 t3 再次获取锁的时候,不会触发重新偏向为线程 t3.


此刻,触发批量撤销,此对象碰撞变为轻量级锁


image.png


最后我们看一下新生成的对象。本来应该是可偏向状态,但是在经历过批量重偏向,和批量撤销之后转换为无锁。


image.png


批量重偏向和批量撤销总结


  • 批量重偏向和批量撤销针对类的优化,和对象无关。


  • 批量锁重新偏向一次过后不能重新偏向。


  • 当某个类已经触发批量撤销机制后, JVM 会默认当前类长生了严重的问题,剥夺了该类新生成对象偏向锁的权利。


参考资料






相关文章
|
1月前
|
前端开发 Java 编译器
深入理解jvm - 编译优化(上)
深入理解jvm - 编译优化(上)
95 0
|
1月前
|
缓存 监控 算法
jvm性能调优实战 - 39一次大促导致的内存泄漏和Full GC优化
jvm性能调优实战 - 39一次大促导致的内存泄漏和Full GC优化
111 0
|
1月前
|
架构师 Java
jvm性能调优实战 - 35电商APP后台系统如何对Full GC进行深度优化
jvm性能调优实战 - 35电商APP后台系统如何对Full GC进行深度优化
65 0
|
17天前
|
监控 前端开发 Java
JVM系列9-后端编译与优化
JVM系列9-后端编译与优化
12 1
|
2天前
|
存储 缓存 Java
JVM的即时编译(JIT)优化原理:加速程序的执行
JVM的即时编译(JIT)优化原理:加速程序的执行
|
2天前
|
Java UED 开发者
JVM逃逸分析原理解析:优化Java程序性能和内存利用效率
JVM逃逸分析原理解析:优化Java程序性能和内存利用效率
|
2天前
|
存储 缓存 监控
深入解析JVM内存分配优化技术:TLAB
深入解析JVM内存分配优化技术:TLAB
|
17天前
|
缓存 自然语言处理 前端开发
JVM系列8-前端编译与优化
JVM系列8-前端编译与优化
10 0
|
23天前
|
Java 应用服务中间件 Linux
Tomcat 调优及 JVM 参数优化
Tomcat 调优及 JVM 参数优化
|
1月前
|
缓存 算法 Java
深入理解jvm - 编译优化(下)
深入理解jvm - 编译优化(下)
56 0