成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

面試官超級喜歡問的MarkWord

開發 后端
續上次被問到synchronized鎖后,面試官繼續刁難阿巴阿巴,進而深入到對象頭中相關的概念。

[[441998]]

前言

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

續上次被問到synchronized鎖后,面試官繼續刁難阿巴阿巴,進而深入到對象頭中相關的概念。

當場拿offer

面試官: 上次提到了synchronized鎖,那你知道synchronized鎖具體是怎么實現的嗎?

阿巴阿巴: 在JDK版本1.5及之前的版本synchronized主要靠的是Monitor對象來完成,同步代碼塊使用的是monitorenter和monitorexit指令,而synchronized修飾方法靠的是ACC_SYNCHRONIZED標識,這些都是進入到內核態進行加鎖的,然后將競爭鎖失敗的線程直接掛起,等待后面恢復。

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

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

MarkWord 對象標記字段,默認存儲的是對象的HashCode,GC的分代年齡(2bit最大表示15)和鎖的標志信息等。對于32位的虛擬機MarkWord占32bit,對于64位的虛擬機MarkWord占用64字節。

Klass Pointer Class 對象的類型指針,它指向對象對應的Class對象的內存地址。大小占4字節(指針壓縮的情況下為4字節,未進行指針壓縮則占8字節)。32位虛擬機MarkWord分布

64位虛擬機MarkWord分布

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

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

面試官: 我們怎么看對象頭里的MarkWord數據呢?

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

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

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

src/hotspot/share/oops/markWord.hpp

  1. // 查看虛擬機是多少位的可以使用: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) 

阿巴阿巴: 當然可以引入openjdk提供的jol-core,然后進行打印即可。

  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看起來是被壓縮了,怎么確定是被壓縮了呢?可以通過如下命令

面試官: 對于JDK1.6及以上版本,synchronized和MarkWord有啥關系嘛?

阿巴阿巴: 那關系可大了,可以看到在MarkWord中有2bit用來表示鎖的標志位,代表著經過優化的synchronized鎖不會直接上重量級鎖,而是由偏向鎖轉為輕量鎖,再由輕量鎖轉為重量級鎖,一步一步膨脹的過程。

下面是2bit的鎖標志位代表的含義

  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  無鎖狀態 (第一位代表偏向標志,為0的時候表示不偏向,為1的時候表示偏向) 
  8. 101  偏向鎖 且記錄線程ID 
  9. 00   輕量鎖 指向棧中鎖記錄的指針 
  10. 10   重量級鎖 重量級鎖的指針 
  11. 11   GC標志 

然后再找到上圖Value部分的數據,這兩位是鎖的標志位

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

阿巴阿巴: 鎖的偏向標志就在鎖標志的前一位

阿巴阿巴: 程序啟動后4s就會加偏向鎖,只不過這個偏向鎖沒有偏向任何線程ID,也屬于無鎖狀態

阿巴阿巴: 當應用處于單線程環境中時,這時候上的是偏向鎖,在對象頭中偏向標示顯示為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.  } 

打印出來的數據如下

阿巴阿巴: 讓程序處于2個線程交替進行競爭鎖

  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運行完 
  11.         thread.join(); 
  12.          
  13.         synchronized (t) { 
  14.             System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  15.         } 
  16.     } 

可以看到當main線程拿鎖時已經膨脹為輕量鎖了,鎖的2bit標志為變成00了

阿巴阿巴: 輕量鎖的時候,虛擬機會在當前線程的棧幀中建立一個鎖記錄的空間“Lock Record”,用于存儲鎖對象目前的MarkWord的拷貝,這一步采用CAS,如果成功了,那么與此同時,2bit的鎖標記位會從“01”轉變為“00”。這就是加輕量鎖的過程。

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

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

  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運行完 
  11.         // thread.join(); 去掉該代碼 
  12.  
  13.         synchronized (t) { 
  14.             System.out.println(ClassLayout.parseInstance(t).toPrintable()); 
  15.         } 
  16.     } 

控制臺打印如下,發現已經加上重量鎖了,鎖的2bit標志為變成10了。

阿巴阿巴: 當輕量級鎖升級成重量級鎖時,Mark Word的鎖標記位更新為10,Mark Word 將指向互斥量(重量級鎖)。

阿巴阿巴: 以上就是關于synchronized和MarkWord的關系啦。

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

阿巴阿巴: 好的~

 

責任編輯:姜華 來源: 程序員巴士
相關推薦

2021-11-08 09:18:01

CAS面試場景

2021-12-16 18:38:13

面試Synchronize

2021-12-02 18:20:25

算法垃圾回收

2022-01-05 08:56:20

Vue修飾符面試

2024-03-25 11:03:38

Vue修飾符lazy

2018-05-10 15:48:47

面試面試官Java

2025-06-03 07:05:00

Linux操作系統Windows

2020-07-28 00:58:20

IP地址子網TCP

2010-08-23 15:06:52

發問

2021-01-06 05:36:25

拉鏈表數倉數據

2022-01-05 09:55:26

asynawait前端

2018-01-19 10:43:06

Java面試官volatile關鍵字

2021-04-21 09:28:17

字節面試官SetTimeout

2024-08-19 09:13:02

2024-06-04 07:38:10

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

2021-03-24 10:25:24

優化VUE性能
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 日韩在线精品强乱中文字幕 | 久久国产亚洲 | 久草精品视频 | 免费观看的av | 超碰操 | 51ⅴ精品国产91久久久久久 | 男人天堂免费在线 | 青青草免费在线视频 | 人人亚洲 | 中文字幕一区二区三区在线观看 | 国产精品国产三级国产a | 国产精品伦一区二区三级视频 | 欧美性猛片aaaaaaa做受 | av中文在线播放 | 日本免费一区二区三区 | 日韩一区在线播放 | 国产 欧美 日韩 一区 | 欧美一区二区三区高清视频 | 国产精品视频久久 | 九色国产 | 狠狠操av | 一道本不卡视频 | 日韩在线高清 | 国产精品久久国产精品 | 中文字幕日韩欧美一区二区三区 | 欧美另类视频 | 亚洲精品一区在线观看 | 国产在线一 | 一区二区三区四区在线视频 | 美女露尿口视频 | 久久99精品国产 | a视频在线观看 | 国外成人在线视频 | 在线色网| 91大神在线资源观看无广告 | 欧美日韩一 | 午夜视频免费在线观看 | 久操国产 | 祝你幸福电影在线观看 | 华丽的挑战在线观看 | 亚洲国产精品一区二区三区 |