一、JVM参数设置参考
-
关闭延迟:-XX:BiasedLockingStartupDelay=0
-
设置JVM关闭偏向锁:-XX:UseBiasedLocking=false
-
打印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())); } } }
打印结果:
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)