偏向鎖是個什么東東?


  上次我們說了對象頭是個什么東東?,但是從我們跑的代碼輸出卻看不到偏向鎖這個東東。為啥對象實例化出來之后,對象頭里是不支持偏向的呢?其實是JVM搞的鬼,JVM雖然默認啟用偏向鎖,但啟動后4秒內並不支持。可以通過-XX:BiasedLockingStartupDelay=0參數將JVM啟動后支持偏向鎖的延遲時間設置為0,這樣就可以看到偏向鎖的輸出了:

 

 

  代碼也改動一下:

import com.wlf.springcloudgateway.javabean.HelloWorld;
import org.openjdk.jol.info.ClassLayout;

import java.util.concurrent.TimeUnit;

public class ObjectMarkWord {

    public static void main(String[] args) throws InterruptedException {

//        TimeUnit.SECONDS.sleep(5); // 啟用偏向鎖,要么開啟jvm參數-XX:BiasedLockingStartupDelay=0,要么等待5秒

        // 實例化對象
        HelloWorld helloWorld = HelloWorld.builder().name("wlf").build();

        // 1、普通對象,無鎖
        System.out.println("無鎖,可偏向:");
        printfObjMarkWord(helloWorld);

        // 2、單線程首次加鎖,偏向鎖
        System.out.println("偏向鎖:");
        new Thread(() -> {
            System.out.println("首次偏向:");
            synchronized (helloWorld) {
                printfObjMarkWord(helloWorld);
            }

            System.out.println("第二次,重偏向:");
            synchronized (helloWorld) {
                printfObjMarkWord(helloWorld);
                try {
                    TimeUnit.SECONDS.sleep(1);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }).start();
        TimeUnit.SECONDS.sleep(1);

        // 3、多個線程加鎖,膨脹為重量鎖
        System.out.println("重量鎖:");
        for (int i = 0; i < 2; i++) {
            new Thread(() -> {
                synchronized (helloWorld) {
                    printfObjMarkWord(helloWorld);
                }
            }).start();
        }
    }

    private static void printfObjMarkWord(Object obj) {
        System.out.println("-------------------------");
        System.out.println(ClassLayout.parseInstance(obj).toPrintable());
        System.out.println("-------------------------");

    }

}

 

  輸出結果:

無鎖,可偏向:
-------------------------
# WARNING: Unable to attach Serviceability Agent. You can try again with escalated privileges. Two options: a) use -Djol.tryWithSudo=true to try with sudo; b) echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
偏向鎖:
首次偏向:
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 00 93 19 (00000101 00000000 10010011 00011001) (429064197)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
第二次,重偏向:
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           05 00 93 19 (00000101 00000000 10010011 00011001) (429064197)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
重量鎖:
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           9a 7b c2 02 (10011010 01111011 11000010 00000010) (46300058)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------
-------------------------
com.wlf.springcloudgateway.javabean.HelloWorld object internals:
 OFFSET  SIZE               TYPE DESCRIPTION                               VALUE
      0     4                    (object header)                           9a 7b c2 02 (10011010 01111011 11000010 00000010) (46300058)
      4     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
      8     4                    (object header)                           88 49 1c 17 (10001000 01001001 00011100 00010111) (387729800)
     12     4                    (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)
     16     8   java.lang.String HelloWorld.name                           (object)
Instance size: 24 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

-------------------------

Process finished with exit code 0

 

  我們看到偏向鎖在對象實例化后打開了(偏向鎖狀態為1,鎖狀態為01),第一次使用鎖的時候就是用的偏向鎖,持有鎖的線程ID被寫入對象頭中,第二次該線程再次使用偏向鎖,線程ID不變。隨后我們使用兩個其他線程來競爭該鎖,偏向鎖膨脹為重量鎖(鎖狀態10),原線程ID變更為持有鎖的線程指針。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM