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());

    }
}

测试结果:

posted @ 2022-03-21 16:35  s686编程传  阅读(117)  评论(0编辑  收藏  举报