一、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)