自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

面試官超級(jí)喜歡問的MarkWord

開發(fā) 后端
續(xù)上次被問到synchronized鎖后,面試官繼續(xù)刁難阿巴阿巴,進(jìn)而深入到對(duì)象頭中相關(guān)的概念。

[[441998]]

前言

年底了,最近好幾天沒吃飯了,在微博吃瓜吃的飽飽的。

續(xù)上次被問到synchronized鎖后,面試官繼續(xù)刁難阿巴阿巴,進(jìn)而深入到對(duì)象頭中相關(guān)的概念。

當(dāng)場(chǎng)拿offer

面試官: 上次提到了synchronized鎖,那你知道synchronized鎖具體是怎么實(shí)現(xiàn)的嗎?

阿巴阿巴: 在JDK版本1.5及之前的版本synchronized主要靠的是Monitor對(duì)象來完成,同步代碼塊使用的是monitorenter和monitorexit指令,而synchronized修飾方法靠的是ACC_SYNCHRONIZED標(biāo)識(shí),這些都是進(jìn)入到內(nèi)核態(tài)進(jìn)行加鎖的,然后將競(jìng)爭(zhēng)鎖失敗的線程直接掛起,等待后面恢復(fù)。

阿巴阿巴: 在JDK1.6及之后的版本中,synchronized鎖得到了優(yōu)化,引入了自適應(yīng)自旋鎖、偏向鎖、輕量鎖,他們主要優(yōu)化了鎖在一定條件下的性能。避免了一上來就加重量級(jí)鎖,等待鎖的其他線程只能乖乖掛起,對(duì)cpu性能影響特別大。

阿巴阿巴: 在hotspot虛擬機(jī)中,對(duì)象頭主要包括兩部分 MarkWord和Klass Pointer。

MarkWord 對(duì)象標(biāo)記字段,默認(rèn)存儲(chǔ)的是對(duì)象的HashCode,GC的分代年齡(2bit最大表示15)和鎖的標(biāo)志信息等。對(duì)于32位的虛擬機(jī)MarkWord占32bit,對(duì)于64位的虛擬機(jī)MarkWord占用64字節(jié)。

Klass Pointer Class 對(duì)象的類型指針,它指向?qū)ο髮?duì)應(yīng)的Class對(duì)象的內(nèi)存地址。大小占4字節(jié)(指針壓縮的情況下為4字節(jié),未進(jìn)行指針壓縮則占8字節(jié))。32位虛擬機(jī)MarkWord分布

64位虛擬機(jī)MarkWord分布

圖片來源https://blog.csdn.net/weixin_40816843/article/details/120811181

查看虛擬機(jī)是多少位的可以使用:java -version

面試官: 我們?cè)趺纯磳?duì)象頭里的MarkWord數(shù)據(jù)呢?

阿巴阿巴: 可以看到在openJDK中關(guān)于MarkWord的描述,首先可以在Github上找到Open Jdk的源碼

gitHub地址:https://github.com/openjdk/jdk

在IDE中打開并找到如下的位置

src/hotspot/share/oops/markWord.hpp

  1. // 查看虛擬機(jī)是多少位的可以使用:java -version   
  2. //  32 bits: 
  3. //  -------- 
  4. //            hash:25 ------------>| age:4  unused_gap:1  lock:2 (normal object) 
  5. // 
  6. //  64 bits: 
  7. //  -------- 
  8. //  unused:25 hash:31 -->| unused_gap:1  age:4  unused_gap:1  lock:2 (normal object) 

阿巴阿巴: 當(dāng)然可以引入openjdk提供的jol-core,然后進(jìn)行打印即可。

  1. // 在pom中引入 
  2. <dependency> 
  3.   <groupId>org.openjdk.jol</groupId> 
  4.   <artifactId>jol-core</artifactId> 
  5.   <version>0.10</version> 
  6. </dependency> 

然后編寫如下代碼

  1. public static void main(String[] args) { 
  2.      Test t = new Test(); 
  3.      System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  4.  } 

打印如下

markword在哪?Klass pointer在哪兒?

1處是MarkWord占用8Byte也就是64bit

2處是Klass Pointer占用了4Byte也就是32bit

klass pointer看起來是被壓縮了,怎么確定是被壓縮了呢?可以通過如下命令

面試官: 對(duì)于JDK1.6及以上版本,synchronized和MarkWord有啥關(guān)系嘛?

阿巴阿巴: 那關(guān)系可大了,可以看到在MarkWord中有2bit用來表示鎖的標(biāo)志位,代表著經(jīng)過優(yōu)化的synchronized鎖不會(huì)直接上重量級(jí)鎖,而是由偏向鎖轉(zhuǎn)為輕量鎖,再由輕量鎖轉(zhuǎn)為重量級(jí)鎖,一步一步膨脹的過程。

下面是2bit的鎖標(biāo)志位代表的含義

  1. //    [ptr             | 00]  locked      ptr points to real header on stack 
  2. //    [header          | 01]  unlocked    regular object header 
  3. //    [ptr             | 10]  monitor     inflated lock (header is wapped out
  4. //    [ptr             | 11]  marked      used to mark an object 
  5. //    [0 ............ 0| 00]  inflating   inflation in progress 
  6.  
  7. 001  無鎖狀態(tài) (第一位代表偏向標(biāo)志,為0的時(shí)候表示不偏向,為1的時(shí)候表示偏向) 
  8. 101  偏向鎖 且記錄線程ID 
  9. 00   輕量鎖 指向棧中鎖記錄的指針 
  10. 10   重量級(jí)鎖 重量級(jí)鎖的指針 
  11. 11   GC標(biāo)志 

然后再找到上圖Value部分的數(shù)據(jù),這兩位是鎖的標(biāo)志位

面試官: 你剛不是說有一位是鎖的偏向標(biāo)志嗎?在哪兒呢?

阿巴阿巴: 鎖的偏向標(biāo)志就在鎖標(biāo)志的前一位

阿巴阿巴: 程序啟動(dòng)后4s就會(huì)加偏向鎖,只不過這個(gè)偏向鎖沒有偏向任何線程ID,也屬于無鎖狀態(tài)

阿巴阿巴: 當(dāng)應(yīng)用處于單線程環(huán)境中時(shí),這時(shí)候上的是偏向鎖,在對(duì)象頭中偏向標(biāo)示顯示為1,案例如下

  1. public static void main(String[] args) { 
  2.      Test t = new Test(); 
  3.      new Thread(()->{ 
  4.          synchronized (t) { 
  5.              System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  6.          } 
  7.      }).start(); 
  8.  } 

打印出來的數(shù)據(jù)如下

阿巴阿巴: 讓程序處于2個(gè)線程交替進(jìn)行競(jìng)爭(zhēng)鎖

  1. public static void main(String[] args) throws InterruptedException { 
  2.         Test t = new Test(); 
  3.         Thread thread = new Thread(()->{ 
  4.             synchronized (t) { 
  5.                 System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  6.             } 
  7.  
  8.         }); 
  9.         thread.start(); 
  10.         // 等待thread運(yùn)行完 
  11.         thread.join(); 
  12.          
  13.         synchronized (t) { 
  14.             System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  15.         } 
  16.     } 

可以看到當(dāng)main線程拿鎖時(shí)已經(jīng)膨脹為輕量鎖了,鎖的2bit標(biāo)志為變成00了

阿巴阿巴: 輕量鎖的時(shí)候,虛擬機(jī)會(huì)在當(dāng)前線程的棧幀中建立一個(gè)鎖記錄的空間“Lock Record”,用于存儲(chǔ)鎖對(duì)象目前的MarkWord的拷貝,這一步采用CAS,如果成功了,那么與此同時(shí),2bit的鎖標(biāo)記位會(huì)從“01”轉(zhuǎn)變?yōu)?ldquo;00”。這就是加輕量鎖的過程。

阿巴阿巴: 之所以引入偏向鎖,是為了解決在無多線程競(jìng)爭(zhēng)環(huán)境下的輕量鎖,輕量鎖CAS多次的嘗試也是對(duì)性能的損耗。相對(duì)于輕量鎖而言,偏向鎖值只需要進(jìn)行一次CAS,這次CAS是用來設(shè)置線程ID的,設(shè)置成功后就代表獲取鎖了。輕量鎖更適合于線程交替執(zhí)行的場(chǎng)景,它們通過CAS自旋,避免了線程直接掛起以及掛起后的恢復(fù)過程,以此來降低CPU的損耗。

阿巴阿巴: 最后讓我們看看加上重量鎖后的MarkWord表現(xiàn)吧,先上代碼

  1. public static void main(String[] args) throws InterruptedException { 
  2.         Test t = new Test(); 
  3.         Thread thread = new Thread(()->{ 
  4.             synchronized (t) { 
  5.                 System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  6.             } 
  7.  
  8.         }); 
  9.         thread.start(); 
  10.         // 等待thread運(yùn)行完 
  11.         // thread.join(); 去掉該代碼 
  12.  
  13.         synchronized (t) { 
  14.             System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  15.         } 
  16.     } 

控制臺(tái)打印如下,發(fā)現(xiàn)已經(jīng)加上重量鎖了,鎖的2bit標(biāo)志為變成10了。

阿巴阿巴: 當(dāng)輕量級(jí)鎖升級(jí)成重量級(jí)鎖時(shí),Mark Word的鎖標(biāo)記位更新為10,Mark Word 將指向互斥量(重量級(jí)鎖)。

阿巴阿巴: 以上就是關(guān)于synchronized和MarkWord的關(guān)系啦。

面試官: 理解的不錯(cuò),明天來上班吧~

阿巴阿巴: 好的~

 

責(zé)任編輯:姜華 來源: 程序員巴士
相關(guān)推薦

2021-11-08 09:18:01

CAS面試場(chǎng)景

2021-12-16 18:38:13

面試Synchronize

2021-12-02 18:20:25

算法垃圾回收

2024-03-25 11:03:38

Vue修飾符lazy

2022-01-05 08:56:20

Vue修飾符面試

2018-05-10 15:48:47

面試面試官Java

2020-07-28 00:58:20

IP地址子網(wǎng)TCP

2010-08-23 15:06:52

發(fā)問

2021-01-06 05:36:25

拉鏈表數(shù)倉數(shù)據(jù)

2022-01-05 09:55:26

asynawait前端

2018-01-19 10:43:06

Java面試官volatile關(guān)鍵字

2021-04-21 09:28:17

字節(jié)面試官SetTimeout

2024-06-04 07:38:10

2024-08-19 09:13:02

2010-10-27 11:07:45

面試官

2021-02-03 15:30:10

面試垃圾回收器前端

2025-03-10 03:00:00

CSSline字體

2023-06-13 07:04:27

2015-08-13 10:29:12

面試面試官

2022-11-04 08:47:52

底層算法數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)