<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          關(guān)于 synchronized 鎖優(yōu)化

          共 24494字,需瀏覽 49分鐘

           ·

          2021-01-18 21:40

          ??眾所周知,讓開發(fā)者簡(jiǎn)單輕松的編寫保證線程安全的代碼,一直是現(xiàn)代編程語(yǔ)言所最求的,Java 也不例外。Java 語(yǔ)言引入的?synchronized?關(guān)鍵字,無(wú)不彰顯它在此方面的勃勃雄心。但理想豐滿現(xiàn)實(shí)骨感,早期的 Java 版本里,對(duì)于此關(guān)鍵字的實(shí)現(xiàn)太過(guò)厚重,導(dǎo)致線程同步的性能遠(yuǎn)不如預(yù)期。Java HotSpot? VM 經(jīng)過(guò)多個(gè)版本的迭代,利用鎖膨脹思想,盡量延遲使用重量級(jí)鎖的手段來(lái)提升?synchronized?原語(yǔ)的性能。

          對(duì)象存儲(chǔ)

          對(duì)象結(jié)構(gòu)

          • 對(duì)象

            對(duì)象在內(nèi)存中的結(jié)構(gòu) (64位 JVM)
            對(duì)象頭 object header
            成員變量 object field
            對(duì)齊/填充(可選) alignment/padding gap (optional)
          • 對(duì)象數(shù)組

            對(duì)象數(shù)組在內(nèi)存中的結(jié)構(gòu) (64位 JVM)
            對(duì)象頭 object header
            數(shù)組元素字節(jié)序列 elements bytes
            對(duì)齊/填充(可選) alignment/padding gap (optional)

          ??由于對(duì)象在內(nèi)存以?8 字節(jié)?為最小單位,單個(gè)對(duì)象占用內(nèi)存字節(jié)不是 8 的倍數(shù)時(shí),需要增加留空字節(jié)湊成倍數(shù),此時(shí)留空的字節(jié)被稱為?對(duì)象對(duì)齊(object alignment)。單個(gè)對(duì)象內(nèi)部的成員變量所占字節(jié)不滿 4 的倍數(shù)時(shí),也需增加留空字節(jié)湊成倍數(shù),此時(shí)的留空字節(jié)被稱為?填充間隙(padding gap)

          對(duì)象頭結(jié)構(gòu)

          • 對(duì)象

            對(duì)象的 Object Hearder 結(jié)構(gòu) (64位 JVM)
            Mark Word (64 位)
            Klass Word(壓縮 32位,不壓縮 64位)1
            對(duì)齊/填充(可選) alignment/padding gap (optional)
          • 對(duì)象數(shù)組

            對(duì)象數(shù)組的 Object Hearder 結(jié)構(gòu) (64位 JVM)
            Mark Word (64 位)
            Klass Word(壓縮 32 位,不壓縮 64 位)
            數(shù)組長(zhǎng)度(32 位)
            對(duì)齊/填充(可選) alignment/padding gap (optional)

          Mark Word 結(jié)構(gòu)

          ??Mark Word,為運(yùn)行時(shí)對(duì)象的標(biāo)記字,字在 32 位系統(tǒng)中占用 32 bit,64 位操作系統(tǒng)占用 64 bit。其記錄著對(duì)象運(yùn)行時(shí)的數(shù)據(jù),包括?identity_hashcodeGC 分代年齡鎖狀態(tài)?等信息。以下引用自 JDK8 HotSpot 源碼?markOop.hpp?中,關(guān)于 Mark Word 結(jié)構(gòu)信息的描述:

          //  32 bits:
          // --------
          // hash:25 ------------>| age:4 biased_lock:1 lock:2 (normal object)
          // JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object)
          // size:32 ------------------------------------------>| (CMS free block)
          // PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)
          //
          // 64 bits:
          // --------
          // unused:25 hash:31 -->| unused:1 age:4 biased_lock:1 lock:2 (normal object)
          // JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object)
          // PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)
          // size:64 ----------------------------------------------------->| (CMS free block)
          //
          // unused:25 hash:31 -->| cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && normal object)
          // JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs && biased object)
          // narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)
          // unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)

          ??為了節(jié)省內(nèi)存空間,64 位的 JVM 采取壓縮普通對(duì)象指針 (COOPs,即 Compressed Ordinary Object Pointer)?2?技術(shù),把對(duì)象指針由原來(lái)的 64 bit 壓縮成 32 bit,進(jìn)而省了一半的內(nèi)存空間。

          ??我們著重關(guān)注 64 位 JVM 的鎖的幾種狀態(tài),也就是通過(guò)上面的?biased_locklock?兩個(gè)標(biāo)志位的排列組合得到:

          biased_locklock狀態(tài)
          001無(wú)鎖 normal object
          101偏向鎖 biased object
          000輕量級(jí)鎖 lightweight/thin object
          010重量級(jí)鎖 heavyweight/fat object
          011GC 標(biāo)記

          鎖的種類

          ??根據(jù) Mark Word 中的鎖狀態(tài),我們分別來(lái)介紹下。

          重量級(jí)鎖

          ??利用系統(tǒng)級(jí)別的互斥量(mutex)實(shí)現(xiàn)同步臨界區(qū),由于系統(tǒng)級(jí)調(diào)用,開銷大,故稱其位重量級(jí)鎖。

          ??在下一節(jié)關(guān)于鎖的狀態(tài)改變圖中,會(huì)發(fā)現(xiàn)一個(gè)?重量級(jí)監(jiān)視器指針,由于它覆蓋(官方稱為?Displaced)了原本的 Mark Word,故它所指向的是復(fù)雜的數(shù)據(jù)結(jié)構(gòu)?ObjectMonitor?就包含有用來(lái)存儲(chǔ)備份的 Mark Word 信息。除此之外,該數(shù)據(jù)結(jié)構(gòu)還包含鎖的等待列表等信息,詳細(xì)可參考?Monitor Object 設(shè)計(jì)模式

          • 優(yōu)點(diǎn):持有鎖時(shí)間長(zhǎng)、競(jìng)爭(zhēng)激烈時(shí),其他等待的線程會(huì)讓出 CPU 進(jìn)入等待列表

          • 缺點(diǎn):系統(tǒng)級(jí)調(diào)用,開銷大

          自旋鎖

          ??利用循環(huán)的方式來(lái)實(shí)現(xiàn)線程等待(忙等),等待期間內(nèi)不讓出 CPU 執(zhí)行時(shí)間、免去系統(tǒng)級(jí)線程切換開銷。

          • 優(yōu)點(diǎn):避免線程切換

          • 缺點(diǎn):等待期間占用 CPU 資源

          輕量級(jí)鎖

          ??采用原子性的?CAS?進(jìn)行加解鎖操作,加鎖失敗時(shí)自旋等待,成功則將 Mark Word 覆蓋成指向線程棧中的?Lock Record?指針,此記錄中同樣含有原 Mark Word 記錄的備份信息。CAS 調(diào)用不需系統(tǒng)級(jí)別調(diào)用,故稱為輕量級(jí)鎖。

          • 優(yōu)點(diǎn):無(wú)需系統(tǒng)級(jí)調(diào)用,性能好于重量級(jí)鎖

          • 缺點(diǎn):每次加解鎖都需要一次 CAS 操作,采用自旋忙等,在競(jìng)爭(zhēng)激烈、持有鎖時(shí)間長(zhǎng)會(huì)加重 CPU 負(fù)荷,會(huì)轉(zhuǎn)到重量級(jí)鎖。

          偏向鎖

          ??給當(dāng)前鎖標(biāo)記所屬線程,使得所屬線程進(jìn)入同步臨界區(qū)不用做任何特殊處理,只是簡(jiǎn)單的使用 CAS 操作將所屬線程 ID 記錄到 Mark Word 中,同一線程再次加解鎖時(shí)無(wú)需 CAS 操作。

          • 優(yōu)點(diǎn):只需初始化時(shí)進(jìn)行一次 CAS 操作,之后加解鎖都無(wú)需 CAS 操作

          • 缺點(diǎn):只能單線程無(wú)競(jìng)爭(zhēng)時(shí)使用,一旦有其他線程就必須撤銷轉(zhuǎn)到輕量級(jí)。

          鎖轉(zhuǎn)態(tài)轉(zhuǎn)移

          ??在給新建的對(duì)象分配內(nèi)存時(shí),其對(duì)象頭信息會(huì)按照下圖所示的進(jìn)行分配,同時(shí)隨著線程的競(jìng)爭(zhēng)發(fā)送鎖狀態(tài)的轉(zhuǎn)化:

          狀態(tài)轉(zhuǎn)步驟

          ??具體鎖轉(zhuǎn)移的過(guò)程如下:

          1. 如果偏向鎖機(jī)制是啟用,那么新建的對(duì)象被初始化成匿名的偏向鎖。之所以是匿名,是因?yàn)榇藭r(shí)并沒(méi)有具體偏向的線程 ID。

            • 使用虛擬機(jī)參數(shù)?-XX:-UseBiasedLocking?可以關(guān)閉偏向鎖,默認(rèn)是啟用的。

            • 由于虛擬機(jī)參數(shù)?-XX:BiasedLockingStartupDelay?默認(rèn) 4 秒,偏向鎖機(jī)制會(huì)延遲 4 秒生效,測(cè)試時(shí)可以將其設(shè)置為 0 秒,防止偏向鎖設(shè)置不生效。

            • 調(diào)用對(duì)象默認(rèn)的?hashCode()、?System.identityHashCode(obj)?方法會(huì)使偏向鎖膨脹為輕量級(jí)鎖?3。原因?yàn)樯傻?identity_hashcode?需要被記錄到 Mark Word 中,而偏向鎖結(jié)構(gòu)沒(méi)有設(shè)計(jì)存儲(chǔ)備份 Mark Word 的指針,類似輕量級(jí)鎖的?lock record pointer、重量級(jí)鎖的?heavyweight monitor pointer

          2. 當(dāng)有單個(gè)線程嘗試獲取該對(duì)象鎖時(shí),將把此線程的 ID 寫入 Mark Word,完成加鎖操作。

          3. 當(dāng)此單線程解鎖時(shí),一直不存在其他線程來(lái)競(jìng)爭(zhēng)時(shí),此時(shí)重偏向 (rebias) 匿名偏向鎖,即無(wú)線程 ID 的偏向鎖。

          4. 一旦有其他線程時(shí)(不管有無(wú)競(jìng)爭(zhēng)),就撤銷偏向 (revoke bias) 轉(zhuǎn)為輕量級(jí)鎖。

            • 其他線程 CAS 操作將自己的線程號(hào) ID 放入 Mark Word 會(huì)失敗,此線程會(huì)執(zhí)行撤銷偏向,在原偏向鎖持有線程到達(dá)安全點(diǎn)后暫停原線程,檢查原線程是否還持有鎖。如果已釋放鎖,將鎖狀態(tài)修改為普通無(wú)鎖狀態(tài);如果未釋放鎖,拷貝 Mark Word 到原偏向鎖線程的鎖記錄中,修改鎖狀態(tài)標(biāo)志位為輕量級(jí),把指向原偏向鎖線程的鎖記錄的指針存入 Mark Word 中,喚醒原持有偏向鎖線程。

            • 原持有偏向鎖線程繼續(xù)從安全點(diǎn)之后運(yùn)行,解鎖時(shí)判斷對(duì)象頭的鎖記錄指針是否指向當(dāng)前線程鎖記錄、且鎖記錄的備份 Mark Word 與現(xiàn)有對(duì)象頭里的 Mark Word 一致,如果都一致說(shuō)明沒(méi)有其他線程等待此鎖,如果不一致說(shuō)明有其他線程等待,釋放鎖之后需要換線掛起的那些線程。

          5. 輕量級(jí)鎖狀態(tài)時(shí),如果競(jìng)爭(zhēng)激烈(等待線程多)、原線程持鎖時(shí)間長(zhǎng)(即其他線程自旋次數(shù)多、等待時(shí)間長(zhǎng))就會(huì)膨脹為重量級(jí)鎖。

          6. 輕量級(jí)、重量級(jí)鎖解鎖后轉(zhuǎn)為普通無(wú)鎖狀態(tài),即后三位為?001

          7. 當(dāng)然,在重量級(jí)鎖狀態(tài)時(shí),如果競(jìng)爭(zhēng)轉(zhuǎn)為不激烈時(shí),鎖會(huì)降級(jí)為輕量級(jí)狀態(tài)。

          狀態(tài)轉(zhuǎn)移驗(yàn)證源代碼

          代碼依賴



          junit
          junit
          4.12
          test


          org.openjdk.jol
          jol-cli
          0.10


          代碼結(jié)構(gòu)

          project
          └── src
          │ └── test
          │ │ └── java
          │ │ │ └── org
          │ │ │ │ └── reion
          │ │ │ │ │ └── LockTest.java
          │ └── main
          │ │ └── resources
          │ │ └── java
          │ │ │ └── org
          │ │ │ │ └── reion
          │ │ │ │ │ └── Student.java

          代碼清單

          • Student.java

              package org.reion;

            /**
            * 學(xué)生
            */

            public class Student {
            // 名
            String firstName;
            // 姓
            String lastName;
            }
          • LockTest.java

              package org.reion;

            import org.junit.Before;
            import org.junit.Test;
            import java.util.Random;
            import org.openjdk.jol.info.ClassLayout;

            import static java.lang.System.out;

            public class OopTest {

            public static final String LINE_SEPARATOR = "\n<<============= %s ==============>>";

            Student stu1;

            @Before
            public void before() {
            stu1 = new Student();
            }

            // 具體測(cè)試方法在下面單個(gè)列出,此處省略
            }

          偏向鎖

          • 測(cè)試方法

            	
            /**
            * 該方法驗(yàn)證對(duì)象初始化后,由單個(gè)線程持有時(shí)的偏向鎖形態(tài)。
            */

            @Test
            public void testBiasedLock() throws InterruptedException {
            // 確保代碼運(yùn)行時(shí),已經(jīng)啟用偏向鎖機(jī)制,有兩種方式:
            // ① 偏向鎖機(jī)制默認(rèn)延遲 4 秒啟動(dòng),故休眠 5 秒
            Thread.sleep(5000);
            // stu1 之所以重新賦值,因?yàn)?before 里舊對(duì)象由于偏向鎖延遲啟動(dòng)機(jī)制,生成不可偏向的對(duì)象
            stu1 = new Student();
            // ② 添加虛擬機(jī)參數(shù),把默認(rèn)延遲修改為 0 秒,虛擬機(jī)啟動(dòng)立馬啟用偏向鎖機(jī)制
            // -XX:BiasedLockingStartupDelay=0

            //【未加鎖,可偏向】
            out.println(String.format(LINE_SEPARATOR, "未加鎖,可偏向"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());

            //【偏向鎖】
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, "偏向鎖"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());
            }

            //【未加鎖,可偏向】
            out.println(String.format(LINE_SEPARATOR, "未加鎖,可偏向"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());
            }
          • 輸出結(jié)果

              <<============= 未加鎖,可偏向 ==============>>
            # 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
            org.reion.Student 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) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= 偏向鎖 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 05 a8 00 b9 (00000101 10101000 00000000 10111001) (-1191139323)
            4 4 (object header) e1 7f 00 00 (11100001 01111111 00000000 00000000) (32737)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= 未加鎖,可偏向 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 05 a8 00 b9 (00000101 10101000 00000000 10111001) (-1191139323)
            4 4 (object header) e1 7f 00 00 (11100001 01111111 00000000 00000000) (32737)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

          注意:?由于 JVM 為?小端法(Little Endian)?故低字節(jié)在前,高字節(jié)在后。

          因此:

          打印結(jié)果中 object header 中 64 位 Mark Word 字節(jié)序列應(yīng)該為
          00 00 7f e1 b9 00 a8 05

          輕量級(jí)鎖

          • 測(cè)試方法

              /**
            * 該方法驗(yàn)證調(diào)用默認(rèn) hashCode 或 System.identityHashCode 時(shí),變?yōu)檩p量級(jí)鎖的形態(tài)
            */

            @Test
            public void testThinLock() {
            // 調(diào)用 System.identityHashCode(stu1) 使對(duì)象 stu1 禁用偏向鎖
            // TIPS:
            // 讓對(duì)象能夠利用上偏向鎖機(jī)制,應(yīng)該重載對(duì)象的 hashCode 方法,
            // 避免 identityHashCode 方法調(diào)用,直接膨脹為輕量級(jí)鎖
            out.println(String.format(LINE_SEPARATOR, "System.identityHashCode 方法調(diào)用"));
            out.println(Integer.toHexString(stu1.hashCode()));

            //【未加鎖,不可偏向】
            out.println(String.format(LINE_SEPARATOR, "未加鎖,不可偏向"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());

            //【輕量級(jí)鎖】
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, "輕量鎖"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());
            }

            //【未加鎖,不可偏向】
            out.println(String.format(LINE_SEPARATOR, "未加鎖,不可偏向"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());
            }
          • 輸出結(jié)果

              <<============= System.identityHashCode 方法調(diào)用 ==============>>
            6aa8ceb6

            <<============= 未加鎖,不可偏向 ==============>>
            # 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
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 b6 ce a8 (00000001 10110110 11001110 10101000) (-1462847999)
            4 4 (object header) 6a 00 00 00 (01101010 00000000 00000000 00000000) (106)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= 輕量鎖 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 88 18 94 01 (10001000 00011000 10010100 00000001) (26482824)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= 未加鎖,不可偏向 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 b6 ce a8 (00000001 10110110 11001110 10101000) (-1462847999)
            4 4 (object header) 6a 00 00 00 (01101010 00000000 00000000 00000000) (106)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

          偏向鎖 -> 輕量級(jí)鎖

          • 測(cè)試方法

              /**
            * 該方法驗(yàn)證第二個(gè)線程出現(xiàn)時(shí)(此時(shí)第二線程已經(jīng)在第一個(gè)線程解鎖后才執(zhí)行,故無(wú)競(jìng)爭(zhēng)),會(huì)撤銷偏向,變?yōu)檩p量級(jí)鎖的形態(tài)。
            */

            @Test
            public void testBias2ThinLock() throws InterruptedException {
            // 調(diào)用偏向鎖方法,生成可偏向的 stu1 對(duì)象
            testBiasedLock();

            // 生成新線程,申請(qǐng)對(duì)象 stu1 鎖
            out.println("當(dāng)前線程:" + Thread.currentThread());
            Runnable runnable = () -> {
            out.println("\n進(jìn)入線程:" + Thread.currentThread());
            out.println(String.format(LINE_SEPARATOR, "未請(qǐng)求鎖,可偏向"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());

            //【偏向鎖 -膨脹-> 輕量級(jí)鎖】
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, "已加鎖,膨脹為輕量級(jí)鎖"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());
            }

            //【未加鎖,不可偏向】
            out.println(String.format(LINE_SEPARATOR, "未加鎖,不可偏向"));
            out.println(ClassLayout.parseInstance(stu1).toPrintable());
            out.println("\n退出線程:" + Thread.currentThread());
            };

            Thread thread = new Thread(runnable);
            thread.start();
            thread.join();
            }
          • 輸出結(jié)果

              當(dāng)前線程:Thread[main,5,main]

            進(jìn)入線程:Thread[Thread-1,5,main]

            <<============= 未請(qǐng)求鎖,可偏向 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 05 d0 00 be (00000101 11010000 00000000 10111110) (-1107243003)
            4 4 (object header) fb 7f 00 00 (11111011 01111111 00000000 00000000) (32763)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= 已加鎖,膨脹為輕量級(jí)鎖 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 08 c9 3e 06 (00001000 11001001 00111110 00000110) (104777992)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= 未加鎖,不可偏向 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
            4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

          輕量級(jí)鎖維持

          • 測(cè)試方法

              /**
            * 該方法驗(yàn)證低競(jìng)爭(zhēng)度時(shí),輕量級(jí)鎖能一直維持此狀態(tài),從而提高運(yùn)行效率
            */

            @Test
            public void testLowContentionThinLock() throws InterruptedException {
            // 調(diào)用 testBias2ThinLock,使 stu1 經(jīng)歷 偏向鎖 -> 輕量鎖 過(guò)程
            // 最終使 stu1 成為 未加鎖不可偏
            testBias2ThinLock();

            Runnable runnable = () -> {
            Thread current = Thread.currentThread();
            out.println("\n進(jìn)入線程:" + current);

            //【輕量級(jí)鎖】
            for (int i = 0; i<2; i++) {
            try {
            // 400 毫秒內(nèi)的隨機(jī)休眠時(shí)間,模擬低對(duì)象鎖競(jìng)爭(zhēng)
            Thread.sleep(new Random().nextInt(400));
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, current + " ROUND-" + i) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
            }
            out.println("\n退出線程:" + Thread.currentThread());
            };

            Thread t1 = new Thread(runnable);
            Thread t2 = new Thread(runnable);
            t1.start();
            t2.start();
            t1.join();
            t2.join();

            // 結(jié)束競(jìng)爭(zhēng)后對(duì)象狀態(tài)
            out.println(String.format(LINE_SEPARATOR, Thread.currentThread()) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
          • 輸出結(jié)果

              進(jìn)入線程:Thread[Thread-2,5,main]

            進(jìn)入線程:Thread[Thread-3,5,main]

            <<============= Thread[Thread-3,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f8 98 1e 11 (11111000 10011000 00011110 00010001) (287217912)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) 83 02 01 f8 (10000011 00000010 00000001 11111000) (-134151549)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-3,5,main] ROUND-1 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f8 98 1e 11 (11111000 10011000 00011110 00010001) (287217912)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) 83 02 01 f8 (10000011 00000010 00000001 11111000) (-134151549)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            退出線程:Thread[Thread-3,5,main]

            <<============= Thread[Thread-2,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f8 68 0e 11 (11111000 01101000 00001110 00010001) (286157048)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) 83 02 01 f8 (10000011 00000010 00000001 11111000) (-134151549)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] ROUND-1 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f8 68 0e 11 (11111000 01101000 00001110 00010001) (286157048)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) 83 02 01 f8 (10000011 00000010 00000001 11111000) (-134151549)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            退出線程:Thread[Thread-2,5,main]

            <<============= Thread[main,5,main] ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
            4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
            8 4 (object header) 83 02 01 f8 (10000011 00000010 00000001 11111000) (-134151549)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

          輕量級(jí)鎖 -> 重量級(jí)鎖 (高頻型)

          • 測(cè)試方法

              /**
            * 該方法驗(yàn)證競(jìng)爭(zhēng)變激烈(請(qǐng)求鎖頻率快)后,鎖由輕量級(jí)膨脹為重量級(jí)的過(guò)程。
            */

            @Test
            public void testHighContentionThin2FatLock() throws InterruptedException {
            // 調(diào)用 testBias2ThinLock,使 stu1 經(jīng)歷 偏向鎖 -> 輕量鎖 過(guò)程
            // 最終使 stu1 成為 未加鎖不可偏
            testBias2ThinLock();

            Runnable runnable = () -> {
            Thread current = Thread.currentThread();
            out.println("\n進(jìn)入線程:" + current);

            //【輕量級(jí)鎖】
            for (int i = 0; i < 2; i++) {
            try {
            // 5 毫秒內(nèi)的隨機(jī)休眠時(shí)間,模擬高對(duì)象鎖競(jìng)爭(zhēng)
            Thread.sleep(new Random().nextInt(5));
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, current + " ROUND-" + i) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
            }
            out.println("\n退出線程:" + Thread.currentThread());
            };

            Thread t1 = new Thread(runnable);
            Thread t2 = new Thread(runnable);
            t1.start();
            t2.start();
            t1.join();
            t2.join();

            // 結(jié)束競(jìng)爭(zhēng)后對(duì)象狀態(tài)
            out.println(String.format(LINE_SEPARATOR, Thread.currentThread()) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
          • 輸出結(jié)果

              <<============= 未加鎖,不可偏向 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
            4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            退出線程:Thread[Thread-1,5,main]

            進(jìn)入線程:Thread[Thread-2,5,main]

            進(jìn)入線程:Thread[Thread-3,5,main]

            <<============= Thread[Thread-2,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) da d3 02 e4 (11011010 11010011 00000010 11100100) (-469576742)
            4 4 (object header) 9a 7f 00 00 (10011010 01111111 00000000 00000000) (32666)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-3,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) da d3 02 e4 (11011010 11010011 00000010 11100100) (-469576742)
            4 4 (object header) 9a 7f 00 00 (10011010 01111111 00000000 00000000) (32666)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] ROUND-1 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) da d3 02 e4 (11011010 11010011 00000010 11100100) (-469576742)
            4 4 (object header) 9a 7f 00 00 (10011010 01111111 00000000 00000000) (32666)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            退出線程:Thread[Thread-2,5,main]

            <<============= Thread[Thread-3,5,main] ROUND-1 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) da d3 02 e4 (11011010 11010011 00000010 11100100) (-469576742)
            4 4 (object header) 9a 7f 00 00 (10011010 01111111 00000000 00000000) (32666)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            退出線程:Thread[Thread-3,5,main]

            <<============= Thread[main,5,main] ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) da d3 02 e4 (11011010 11010011 00000010 11100100) (-469576742)
            4 4 (object header) 9a 7f 00 00 (10011010 01111111 00000000 00000000) (32666)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

          輕量級(jí)鎖 -> 重量級(jí)鎖 (長(zhǎng)時(shí)型)

          • 測(cè)試方法

              /**
            * 該方法驗(yàn)證持鎖時(shí)間長(zhǎng)(等待線程自旋過(guò)多),鎖由輕量級(jí)膨脹為重量級(jí)的過(guò)程。
            */

            @Test
            public void testLongContentionThin2FatLock() throws InterruptedException {
            // 調(diào)用 testBias2ThinLock,使 stu1 經(jīng)歷 偏向鎖 -> 輕量鎖 過(guò)程
            // 最終使 stu1 成為 未加鎖不可偏
            testBias2ThinLock();

            // 長(zhǎng)期持有對(duì)象鎖,在另一個(gè)線程開始競(jìng)爭(zhēng)時(shí),觀察鎖膨脹過(guò)程
            Runnable runnable = () -> {
            Thread current = Thread.currentThread();
            out.println("\n進(jìn)入線程:" + current);

            //【輕量級(jí)鎖】
            synchronized (stu1) {
            int counter = 0;
            while (counter < 5) {
            counter++;
            try {
            Thread.sleep(1000);
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
            out.println(String.format(LINE_SEPARATOR, current + " 鎖內(nèi)") + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
            }

            out.println("\n退出線程:" + current);
            };

            // 睡眠 2.5 秒后,開始競(jìng)爭(zhēng)鎖
            Runnable runnable2 = () -> {
            Thread current = Thread.currentThread();
            out.println("\n進(jìn)入線程:" + current);

            //【輕量級(jí)鎖】
            try {
            out.println(String.format(LINE_SEPARATOR, current + "睡眠...") + "\n\n");
            Thread.sleep(2500);
            } catch (InterruptedException e) {
            e.printStackTrace();
            }

            // 2.5 秒后參與競(jìng)爭(zhēng)
            out.println(String.format(LINE_SEPARATOR, current + "參與競(jìng)爭(zhēng)...") + "\n\n");
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, current) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
            };

            Thread t1 = new Thread(runnable);
            Thread t2 = new Thread(runnable2);
            t1.start();
            t2.start();
            t1.join();
            t2.join();

            }
          • 輸出結(jié)果

              進(jìn)入線程:Thread[Thread-2,5,main]

            進(jìn)入線程:Thread[Thread-3,5,main]

            <<============= Thread[Thread-3,5,main]睡眠... ==============>>



            <<============= Thread[Thread-2,5,main] 鎖內(nèi) ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f0 98 a9 0c (11110000 10011000 10101001 00001100) (212441328)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] 鎖內(nèi) ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f0 98 a9 0c (11110000 10011000 10101001 00001100) (212441328)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-3,5,main]參與競(jìng)爭(zhēng)... ==============>>



            <<============= Thread[Thread-2,5,main] 鎖內(nèi) ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 8a 3c 01 5d (10001010 00111100 00000001 01011101) (1560362122)
            4 4 (object header) d2 7f 00 00 (11010010 01111111 00000000 00000000) (32722)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] 鎖內(nèi) ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 8a 3c 01 5d (10001010 00111100 00000001 01011101) (1560362122)
            4 4 (object header) d2 7f 00 00 (11010010 01111111 00000000 00000000) (32722)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] 鎖內(nèi) ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 8a 3c 01 5d (10001010 00111100 00000001 01011101) (1560362122)
            4 4 (object header) d2 7f 00 00 (11010010 01111111 00000000 00000000) (32722)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            退出線程:Thread[Thread-2,5,main]

            <<============= Thread[Thread-3,5,main] ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 8a 3c 01 5d (10001010 00111100 00000001 01011101) (1560362122)
            4 4 (object header) d2 7f 00 00 (11010010 01111111 00000000 00000000) (32722)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

          輕量級(jí)鎖 -> 重量級(jí)鎖 -> 輕量級(jí)鎖

          • 測(cè)試方法

              /**
            * 該方法驗(yàn)證競(jìng)爭(zhēng)由強(qiáng)轉(zhuǎn)弱后,鎖由輕量級(jí)膨脹為重量級(jí)后又降級(jí)為輕量級(jí)的過(guò)程。
            */

            @Test
            public void testHighContentionThin2FatThenDeflate2ThinLock() throws InterruptedException {
            // 調(diào)用 testBias2ThinLock,使 stu1 經(jīng)歷 偏向鎖 -> 輕量鎖 過(guò)程
            // 最終使 stu1 成為 未加鎖不可偏
            testBias2ThinLock();

            Runnable runnable = () -> {
            Thread current = Thread.currentThread();
            out.println("\n進(jìn)入線程:" + current);

            // 隨機(jī)產(chǎn)生 10 之內(nèi)的循環(huán)追加數(shù),模擬雙線程中,一個(gè)線程完成后,剩下的線程單獨(dú)執(zhí)行時(shí)鎖降級(jí)
            int maxRound = new Random().nextInt(10);
            //【輕量級(jí)鎖】
            for (int i = 0; i < 5 + maxRound; i++) {
            try {
            // 5 毫秒內(nèi)的隨機(jī)休眠時(shí)間,模擬高對(duì)象鎖競(jìng)爭(zhēng)
            Thread.sleep(new Random().nextInt(5));
            } catch (InterruptedException e) {
            e.printStackTrace();
            }
            synchronized (stu1) {
            out.println(String.format(LINE_SEPARATOR, current + " ROUND-" + i) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
            out.println(String.format(LINE_SEPARATOR, current + " ROUND-" + i) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
            out.println("\n退出線程:" + Thread.currentThread());
            };

            Thread t1 = new Thread(runnable);
            Thread t2 = new Thread(runnable);
            t1.start();
            t2.start();
            t1.join();
            t2.join();

            // 結(jié)束競(jìng)爭(zhēng)后對(duì)象狀態(tài)
            out.println(String.format(LINE_SEPARATOR, Thread.currentThread()) + "\n" + ClassLayout.parseInstance(stu1).toPrintable());
            }
          • 輸出結(jié)果

              進(jìn)入線程:Thread[Thread-2,5,main]

            進(jìn)入線程:Thread[Thread-3,5,main]

            <<============= Thread[Thread-2,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f0 a8 25 0f (11110000 10101000 00100101 00001111) (254126320)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
            4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-3,5,main] ROUND-0 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f0 d8 35 0f (11110000 11011000 00110101 00001111) (255187184)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

            <<============= Thread[Thread-3,5,main] ROUND-1 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 5a d1 82 44 (01011010 11010001 10000010 01000100) (1149423962)
            4 4 (object header) dd 7f 00 00 (11011101 01111111 00000000 00000000) (32733)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] ROUND-1 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 5a d1 82 44 (01011010 11010001 10000010 01000100) (1149423962)
            4 4 (object header) dd 7f 00 00 (11011101 01111111 00000000 00000000) (32733)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

            【【【【【【【【中間打印省略】】】】】】】】】
            退出線程:Thread[Thread-3,5,main]

            <<============= Thread[Thread-2,5,main] ROUND-8 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) f0 a8 25 0f (11110000 10101000 00100101 00001111) (254126320)
            4 4 (object header) 00 70 00 00 (00000000 01110000 00000000 00000000) (28672)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total


            <<============= Thread[Thread-2,5,main] ROUND-8 ==============>>
            org.reion.Student object internals:
            OFFSET SIZE TYPE DESCRIPTION VALUE
            0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
            4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
            8 4 (object header) b4 02 01 f8 (10110100 00000010 00000001 11111000) (-134151500)
            12 4 java.lang.String Student.firstName null
            16 4 java.lang.String Student.lastName null
            20 4 (loss due to the next object alignment)
            Instance size: 24 bytes
            Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

            退出線程:Thread[Thread-2,5,main]

          參考資料

          • Synchronization?Created by Christian Wimmer, last modified on Apr 29, 2008

          • Compressed Ordinary Object Pointer

          • markOop.hpp

          • What is in java object header

          腳注

          1. 壓縮的類指針 (Compressed Class Pointer),使用虛擬機(jī)參數(shù)?-XX:-UseCompressedClassPointers?關(guān)閉壓縮,默認(rèn)開啟。

          2. 壓縮的普通對(duì)象指針 (Compressed Ordinary Object Pointer),使用虛擬機(jī)參數(shù)?-XX:-UseCompressedOops?關(guān)閉壓縮,默認(rèn)開啟。

          3. How does the default hashCode() work??

          source:https://reionchan.github.io/2020/08/26/about-synchronized-lock-optimization/

          喜歡,在看


          瀏覽 53
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲视频VS在线免费观看 | 国产精品久久久久久久久久小说 | 超碰美女在线 | 久久久久无码精品人妻 | AA级黄色一级黄色 |