• Synchronized 锁 批量重偏向 和批量撤销


     
    一、JVM参数设置参考
    1. 关闭延迟:-XX:BiasedLockingStartupDelay=0
    2. 设置JVM关闭偏向锁:-XX:UseBiasedLocking=false
    3. 打印JVM启动参数: -XX:+PrintFlagsFinal
     
    二、释义
    1 批量重偏向锁:当对某个类的对象偏向锁批量撤销20次,则偏向锁认为,后面的锁需要重新偏向新的线程(批量重偏向)
    2 批量撤销:当某个类的对象的偏向锁累计被撤销到阈值40次(从40次开始),则偏向锁认为偏向锁撤销过于频繁,则后面的对象包括新生成的对象(标识为101和001)如果需要使用锁,则直接轻量级锁,不在使用偏向锁(即禁用了偏向锁)
     
    三、打印JVM设置
      
     intx BiasedLockingBulkRebiasThreshold          = 20                                  {product}
         intx BiasedLockingBulkRevokeThreshold          = 40                                  {product}
    四、代码案例
     
    static int count=39;//39 则正好是经历了,40次偏向锁撤销,以后新创建的对象为无锁不可偏向标识,那加锁则直接为轻量级锁(撤销了偏向锁这个步骤)
      
    package com.test;
    
    
    import org.openjdk.jol.info.ClassLayout;
    
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.locks.LockSupport;
    
    
    /**
    * Hello world!
    * -XX:+PrintFlagsFinal
    * -Xms1g -Xmx1g  -XX:+PrintGCDetails -XX:BiasedLockingStartupDelay=0 偏向延迟关闭参数
    */
    
    
    public class Test4
    {
        static  Thread t1=null;
        static  Thread t2 = null;
        static  Thread t3 = null;
    
    
        static int count=39;//39 则正好是经历了,40次偏向锁撤销,以后新创建的对象为无锁不可偏向标识,那加锁则直接为轻量级锁(撤销了偏向锁这个步骤)
    
    
        public static void main( String[] args ) throws InterruptedException {
    
    
    //        System.out.println(String.format(" 新对象锁标识:%s ", ClassLayout.parseInstance(new B()).toPrintableTest()));
            B b2 = new B();
            //保存锁对象列表
            List<B> list = new ArrayList<>();
            //第一个线程
            t1 = new Thread(){
                @Override
                public void run() {
                    for (int i = 0; i <count ; i++) {
                        B b = new B();
                        list.add(b);
                        System.out.println(String.format("线程名称 %s 执行的次数 %d ", Thread.currentThread().getName(),i));
                        System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                        synchronized (b){
                            //打印第一个线程加锁后 ,对象头变化
                            System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                        }
                        System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                    }
                    LockSupport.unpark(t2);
                }
            };
    
    
            t2  = new Thread( ){
                @Override
                public void run() {
                    LockSupport.park();
                    System.out.println("线程2开始执行======");
                    for (int i = 0; i <count ; i++) {
                        System.out.println(String.format("线程名称 %s 执行的次数 %d ", Thread.currentThread().getName(),i));
                        B b = list.get(i);
                        System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                        synchronized (list.get(i)){
                            //打印第二个线程对对象加锁,对象头变化(线程前20次为偏向锁升级轻量级锁,从20次开始偏向锁偏向线程t2,发生线程重偏向)
                            System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                        }
                        System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                    }
                    LockSupport.unpark(t3);
                }
            };
    
    
            t3 = new Thread(()->{
                LockSupport.park();
                System.out.println("线程3开始执行========================");
                for (int i = 0; i <count ; i++) {
                    System.out.println(String.format("线程名称 %s 执行的次数 %d ", Thread.currentThread().getName(),i));
                    B b = list.get(i);
                    System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                    synchronized (b){
                        //线程从20个开始进行偏向锁撤销直到发生撤销40次到达阈值,则后面的对象发生 偏向锁 批量撤销
                        System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                    }
                    System.out.println(ClassLayout.parseInstance(b).toPrintableTest());
                }
            });
    
    
            t1.setName("线程t1 ");
            t2.setName("线程t2 ");
            t3.setName("线程t3 ");
    
    
            t1.start();
            t2.start();
            t3.start();
            t1.join();
            t2.join();
            t3.join();
    
    
            System.out.println("= 主线程新====================");
            //发生批量撤销后线程加锁,转换为轻量级锁
            System.out.println(String.format(" 新对象锁标识:%s ", ClassLayout.parseInstance(b2).toPrintableTest()));
            synchronized (b2){
                System.out.println(String.format(" 新对象锁标识:%s ", ClassLayout.parseInstance(b2).toPrintableTest()));
            }
        }
    }
    View Code
    打印结果:
      1) 线程t1打印结果为偏向锁-取了38个打印结果:
          
    1 线程名称 线程t1  执行的次数 38
    2       0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
    3       0     4        (object header)                           05 d0 ed 1f (00000101 11010000 11101101 00011111) (535678981)
    4       0     4        (object header)                           05 d0 ed 1f (00000101 11010000 11101101 00011111) (535678981)

     2)线程t2打印结果为:前19次为偏向锁膨胀为轻量锁,从第20次开始为锁重偏向为线程t2

        

    线程名称 线程t2  执行的次数 18
          0     4        (object header)                           05 d0 ed 1f (00000101 11010000 11101101 00011111) (535678981)
          0     4        (object header)                           10 f4 6e 20 (00010000 11110100 01101110 00100000) (544142352)
          0     4        (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)

      

    线程名称 线程t2  执行的次数 19
          0     4        (object header)                           05 d0 ed 1f (00000101 11010000 11101101 00011111) (535678981)
          0     4        (object header)                           05 e1 ed 1f (00000101 11100001 11101101 00011111) (535683333)
          0     4        (object header)                           05 e1 ed 1f (00000101 11100001 11101101 00011111) (535683333)
     3)从偏向锁撤销40次开始,锁变为轻量级锁
      
    = 主线程新====================
    新对象锁标识:      0     4        (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
    新对象锁标识:      0     4        (object header)                           a0 f5 33 03 (10100000 11110101 00110011 00000011) (53736864)
     
     
     
     
     
     
     
     
  • 相关阅读:
    c# System.Object类和数据的安全转型
    计算机内存的组织方式
    c# ref和out参数
    C# 复制值类型的变量和类
    PCB 布线,直角线,差分线,蛇形线
    c# 静态方法和数据
    c# 类的知识
    appium中从activity切换到html
    No Desktop License Servers available to provide a license
    adb命令连接Android模拟器夜神模拟器
  • 原文地址:https://www.cnblogs.com/lean-blog/p/13719480.html
Copyright © 2020-2023  润新知