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)
 
 
 
 
 
 
 
 
原文地址:https://www.cnblogs.com/lean-blog/p/13719480.html