偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Java中的鎖升級(jí)機(jī)制:偏向鎖、輕量級(jí)鎖和重量級(jí)鎖

開發(fā) 前端
我們需要重點(diǎn)分析MarkWord對象頭,因?yàn)镸arkword 是保存鎖狀態(tài)的關(guān)鍵,對象鎖狀態(tài)可以從偏向鎖升級(jí)到輕量級(jí)鎖,再升級(jí)到重量級(jí)鎖,加上初始的無鎖狀態(tài),可以理解為有 4 種狀態(tài)。想在一個(gè)對象中表示這么多信息自然就要用位來存儲(chǔ)。

Monitor實(shí)現(xiàn)的鎖屬于重量級(jí)鎖,你了解過鎖升級(jí)嗎?

前面我們說了  synchronized 底層由monitor實(shí)現(xiàn)的,它那 synchronized 到底鎖的是什么呢?隨著 JDK 版本的升級(jí),synchronized 又做出了哪些改變呢?“synchronized 性能很差”的謠言真的存在嗎?

在介紹以上內(nèi)容之前,我們要先知道重量級(jí)鎖概念。

重量級(jí)鎖

當(dāng)另外一個(gè)線程執(zhí)行到同步塊的時(shí)候,由于它沒有對應(yīng) monitor 的所有權(quán),就會(huì)被阻塞,此時(shí)控制權(quán)只能交給操作系統(tǒng),也就會(huì)從 user mode 切換到 kernel mode, 由操作系統(tǒng)來負(fù)責(zé)線程間的調(diào)度和線程的狀態(tài)變更, 這就需要頻繁的在這兩個(gè)模式下切換(上下文轉(zhuǎn)換)。有點(diǎn)競爭就找內(nèi)核的行為很不好,會(huì)引起很大的開銷,所以大家都叫它重量級(jí)鎖,自然效率也很低,這也就給很多小伙伴留下了一個(gè)印象 —— synchronized 關(guān)鍵字相比于其他同步機(jī)制性能不好,但其實(shí)不然。

  • Monitor實(shí)現(xiàn)的鎖屬于重量級(jí)鎖,里面涉及到了用戶態(tài)和內(nèi)核態(tài)的切換、進(jìn)程的上下文切換,成本較高,性能比較低。
  • 在JDK 1.6引入了兩種新型鎖機(jī)制:偏向鎖和輕量級(jí)鎖,它們的引入是為了解決在沒有多線程競爭或基本沒有競爭的場景下因使用傳統(tǒng)鎖機(jī)制帶來的性能開銷問題。

一、MarkWord

在JVM虛擬機(jī)中,對象在內(nèi)存中存儲(chǔ)的布局可分為3塊區(qū)域:對象頭(Header)、實(shí)例數(shù)據(jù)(Instance Data)和對齊填充。

圖片圖片

我們需要重點(diǎn)分析MarkWord對象頭,因?yàn)镸arkword 是保存鎖狀態(tài)的關(guān)鍵,對象鎖狀態(tài)可以從偏向鎖升級(jí)到輕量級(jí)鎖,再升級(jí)到重量級(jí)鎖,加上初始的無鎖狀態(tài),可以理解為有 4 種狀態(tài)。想在一個(gè)對象中表示這么多信息自然就要用位來存儲(chǔ)。

圖片圖片

  • hashcode:25位的對象標(biāo)識(shí)Hash碼
  • age:對象分代年齡占4位
  • biased_lock:偏向鎖標(biāo)識(shí),占1位 ,0表示沒有開始偏向鎖,1表示開啟了偏向鎖

thread:持有偏向鎖的線程ID,占23位

  • epoch:偏向時(shí)間戳,占2位
  • ptr_to_lock_record:輕量級(jí)鎖狀態(tài)下,指向棧中鎖記錄的指針,占30位
  • ptr_to_heavyweight_monitor:重量級(jí)鎖狀態(tài)下,指向?qū)ο蟊O(jiān)視器Monitor的指針,占30位

我們可以通過lock的標(biāo)識(shí),來判斷是哪一種鎖的等級(jí)

  • 后三位是001表示無鎖
  • 后三位是101表示偏向鎖
  • 后兩位是00表示輕量級(jí)鎖
  • 后兩位是10表示重量級(jí)鎖

二、輕量級(jí)鎖

在很多的情況下,在Java程序運(yùn)行時(shí),同步塊中的代碼都是不存在競爭的,不同的線程交替的執(zhí)行同步塊中的代碼。這種情況下,用重量級(jí)鎖是沒必要的。因此JVM引入了輕量級(jí)鎖的概念。

如果 CPU 通過 CAS(后面會(huì)細(xì)講,戳鏈接直達(dá))就能處理好加鎖/釋放鎖,這樣就不會(huì)有上下文的切換。

但是當(dāng)競爭很激烈,CAS 嘗試再多也是浪費(fèi) CPU,權(quán)衡一下,不如升級(jí)成重量級(jí)鎖,阻塞線程排隊(duì)競爭,也就有了輕量級(jí)鎖升級(jí)成重量級(jí)鎖的過程。

圖片圖片

作為程序員的我們最喜歡用代碼說話,貼心的 openjdk 官網(wǎng)提供了可以查看對象內(nèi)存布局的工具 JOL (java object layout),我們直接通過 Maven 引入到項(xiàng)目中。

<dependency>
      <groupId>org.openjdk.jol</groupId>
      <artifactId>jol-core</artifactId>
      <version>0.14</version>
  </dependency>
public class SyncSample {


    private static Object LOCK = new Object();

    public static void main(String[] args) {


        System.out.println("----------未進(jìn)入同步塊,MarkWord 為:----------");

        System.out.println(ClassLayout.parseInstance(LOCK).toPrintable());


        synchronized (LOCK) {
            System.out.println("----------進(jìn)入同步塊,MarkWord 為:----------");
            System.out.println(ClassLayout.parseInstance(LOCK).toPrintable());
        }
    }

}

圖片圖片

2.1 加鎖流程

1.在線程棧中創(chuàng)建一個(gè)Lock Record,將其obj字段指向鎖對象。

圖片圖片

2.通過CAS指令將Lock Record的地址存儲(chǔ)在對象頭的mark word中(數(shù)據(jù)進(jìn)行交換),如果對象處于無鎖狀態(tài)則修改成功,代表該線程獲得了輕量級(jí)鎖。

圖片圖片

3.如果是當(dāng)前線程已經(jīng)持有該鎖了,代表這是一次鎖重入。設(shè)置Lock Record第一部分為null,起到了一個(gè)重入計(jì)數(shù)器的作用。

圖片圖片

4.如果CAS修改失敗,說明發(fā)生了競爭,需要膨脹為重量級(jí)鎖。

2.2 解鎖流程

1.遍歷線程棧,找到所有obj字段等于當(dāng)前鎖對象的Lock Record。

2.如果Lock Record的Mark Word為null,代表這是一次重入,將obj設(shè)置為null后continue。

圖片圖片

3.如果Lock Record的 Mark Word不為null,則利用CAS指令將對象頭的mark word恢復(fù)成為無鎖狀態(tài)。如果失敗則膨脹為重量級(jí)鎖。

圖片圖片

三、偏向鎖

輕量級(jí)鎖在沒有競爭時(shí)(就自己這個(gè)線程),每次重入仍然需要執(zhí)行 CAS 操作。Java 6 中引入了偏向鎖來做進(jìn)一步優(yōu)化:只有第一次使用 CAS 將線程 ID 設(shè)置到對象的 Mark Word 頭,之后發(fā)現(xiàn)這個(gè)線程 ID 是自己的就表示沒有競爭,不用重新 CAS。以后只要不發(fā)生競爭,這個(gè)對象就歸該線程所有。

圖片圖片

可是多線程環(huán)境,也不可能只有同一個(gè)線程一直獲取這個(gè)鎖,其他線程也是要干活的,如果出現(xiàn)多個(gè)線程競爭的情況,就會(huì)有偏向鎖升級(jí)的過程。

1.在線程棧中創(chuàng)建一個(gè)Lock Record,將其obj字段指向鎖對象。

圖片圖片

2.通過CAS指令將Lock Record的線程id存儲(chǔ)在對象頭的mark word中,同時(shí)也設(shè)置偏向鎖的標(biāo)識(shí)為101,如果對象處于無鎖狀態(tài)則修改成功,代表該線程獲得了偏向鎖。

圖片圖片

3.如果是當(dāng)前線程已經(jīng)持有該鎖了,代表這是一次鎖重入。設(shè)置Lock Record第一部分為null,起到了一個(gè)重入計(jì)數(shù)器的作用。與輕量級(jí)鎖不同的時(shí),這里不會(huì)再次進(jìn)行cas操作,只是判斷對象頭中的線程id是否是自己,因?yàn)槿鄙倭薱as操作,性能相對輕量級(jí)鎖更好一些。

圖片圖片

思考:偏向鎖可以繞過輕量級(jí)鎖,直接升級(jí)到重量級(jí)鎖嗎?

圖片

四、面試題

面試官:Monitor實(shí)現(xiàn)的鎖屬于重量級(jí)鎖,你了解過鎖升級(jí)嗎?

Java中的synchronized有無鎖(無鎖就是沒有對資源進(jìn)行鎖定,任何線程都可以嘗試去修改它)、偏向鎖、輕量級(jí)鎖、重量級(jí)鎖四種形式,偏向鎖、輕量級(jí)鎖、重量級(jí)鎖分別對應(yīng)了鎖只被一個(gè)線程持有、不同線程交替持有鎖、多線程競爭鎖三種情況

鎖別

描述

重量級(jí)鎖

底層使用的Monitor實(shí)現(xiàn),里面涉及到了用戶態(tài)和內(nèi)核態(tài)的切換、進(jìn)程的上下文切換,成本較高,性能比較低。

輕量級(jí)鎖

線程加鎖的時(shí)間是錯(cuò)開的(也就是沒有競爭),可以使用輕量級(jí)鎖來優(yōu)化。輕量級(jí)修改了對象頭的鎖標(biāo)志,相對重量級(jí)鎖性能提升很多。每次修改都是CAS操作,保證原子性

偏向鎖

一段很長的時(shí)間內(nèi)都只被一個(gè)線程使用鎖,可以使用了偏向鎖,在第一次獲得鎖時(shí),會(huì)有一個(gè)CAS操作,之后該線程再獲取鎖,只需要判斷mark  word中是否是自己的線程id即可,而不是開銷相對較大的CAS命令


責(zé)任編輯:武曉燕 來源: springboot葵花寶典
相關(guān)推薦

2024-08-13 14:08:25

2023-10-10 07:55:41

JDK8輕量級(jí)鎖

2024-09-26 08:22:03

2024-01-11 08:12:20

重量級(jí)監(jiān)視器

2019-10-08 14:40:53

Java線程

2025-03-20 06:48:55

性能優(yōu)化JDK

2024-02-26 07:36:09

lockJava語言

2013-05-15 10:20:16

Paas虛擬化

2022-10-21 16:39:56

JDK優(yōu)化

2019-11-28 16:00:06

重入鎖讀寫鎖樂觀鎖

2024-01-29 01:08:01

悲觀鎖遞歸鎖讀寫鎖

2024-01-08 13:38:00

AI模型

2019-01-04 11:18:35

獨(dú)享鎖共享鎖非公平鎖

2025-06-04 02:55:00

MySQL意向鎖記錄鎖

2009-12-08 10:07:29

2019-10-17 08:51:00

Java悲觀鎖Monitor

2020-05-21 11:02:00

數(shù)據(jù)庫工具 CMDB

2021-12-28 18:23:49

Java指令

2024-09-29 08:39:51

2024-03-06 08:00:56

javaAQS原生
點(diǎn)贊
收藏

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