日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

不吃飯也要掌握的Synchronized鎖升級過程

來源: 責編: 時間:2023-11-08 09:10:54 289觀看
導讀一、前言在面試題中經常會有這么一道面試題,談一下synchronized鎖升級過程?之前背了一些,很多文章也說了,到底怎么什么條件才會觸發升級,一直不太明白。實踐是檢驗真理的唯一標準,今天就和大家一起實踐一下,什么條件才會升級

8gS28資訊網——每日最新資訊28at.com

一、前言

在面試題中經常會有這么一道面試題,談一下synchronized鎖升級過程?8gS28資訊網——每日最新資訊28at.com

之前背了一些,很多文章也說了,到底怎么什么條件才會觸發升級,一直不太明白。8gS28資訊網——每日最新資訊28at.com

實踐是檢驗真理的唯一標準,今天就和大家一起實踐一下,什么條件才會升級!8gS28資訊網——每日最新資訊28at.com

二、為什么會有鎖升級過程?

在實踐之前,我們先一步步的來了解!為什么要升級呢?8gS28資訊網——每日最新資訊28at.com

在JDK1.6之前,synchronized的性能一直沒有ReentrantLock性能高,主要是因為synchronized涉及到用戶態和內核態的切換,這個是在操作系統和硬件是非常消耗資源的。8gS28資訊網——每日最新資訊28at.com

經過不斷的統計分析,發現大部分時間一個鎖都是一個線程去獲取,如果只有一個線程來嘗試加鎖,就是重量級鎖,顯而浪費資源。8gS28資訊網——每日最新資訊28at.com

「總之,鎖的升級過程是為了提高多線程環境下的性能和吞吐量,減少同步操作的開銷,并盡量避免線程切換的開銷。Java虛擬機根據線程競爭的情況和鎖的使用情況自動進行鎖的升級和降級,以優化多線程程序的性能。」8gS28資訊網——每日最新資訊28at.com

此時,就引入了很多鎖類型,下面我們來具體看看!8gS28資訊網——每日最新資訊28at.com

三、鎖分類

偏向鎖:偏向鎖是為了解決單線程訪問的場景,偏向鎖允許第一個訪問共享資源的線程獲得鎖,把線程id存到對象頭中,后續的訪問可以直接獲得鎖,而不需要競爭。8gS28資訊網——每日最新資訊28at.com

輕量級鎖:當一個或多個線程嘗試獲取同一個鎖時,偏向鎖會升級為輕量級鎖。輕量級鎖采用CAS(Compare and Swap)操作來減小鎖的競爭。采用自適應自旋!8gS28資訊網——每日最新資訊28at.com

重量級鎖:操作系統的調度器會介入,將競爭鎖的線程掛起,直到鎖被釋放為止,重量級鎖的開銷相對較高。8gS28資訊網——每日最新資訊28at.com

「補充:」8gS28資訊網——每日最新資訊28at.com

「自適應自旋的基本思想是根據鎖的爭用情況,決定線程是否應該自旋等待,以及自旋等待的時間,一般情況為自旋10次。」8gS28資訊網——每日最新資訊28at.com

四、對象內存結構

我們在說鎖的升級過程之前,需要了解一下對象的內存結構,因為在鎖升級過程中會往對象頭上進行填充信息!一個對象分為:對象頭、實例數據、對其填充位三部分組成。8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

我們本次主要用到對象頭,我們再看一下詳細的對象頭信息里有什么:8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

四、圖解鎖升級過程

先來一個簡圖:8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

下面引用百度上的一張詳細一點的圖:8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

我們來詳細的說一下鎖的升級過程,在每一個鎖切換時的條件是什么?8gS28資訊網——每日最新資訊28at.com

在JDK8時,偏向鎖默認是在程序啟動后4s自動開啟的,在JKD15之后默認是不開啟的!8gS28資訊網——每日最新資訊28at.com

可以設置無延遲時間啟動:-XX:BiasedLockingStartupDelay=0也可以不啟動偏向鎖:-XX:-UseBiasedLocking = false。8gS28資訊網——每日最新資訊28at.com

直接說有點不形象,我們下面結合代碼來實戰,看一下具體情況!8gS28資訊網——每日最新資訊28at.com

五、實戰鎖升級過程

為了我們能夠查詢對象結構,我們需要引入jar幫助我們查看!8gS28資訊網——每日最新資訊28at.com

1、導入依賴

「注意」:不要使用高版本的,高版本不顯示2進制,不好觀察!8gS28資訊網——每日最新資訊28at.com

<dependency>    <groupId>org.openjdk.jol</groupId>    <artifactId>jol-core</artifactId>    <version>0.10</version></dependency>

2、實戰代碼和解析

我們來從序號1開始,上面也說了默認4s后開啟偏向鎖,我們會發現序號1打印的對象頭序號為:001我們的對象大小為20,內部幫我們補位來滿足是8的倍數。方便操作系統進行尋址,不會有碎片組合!這個大家可以詳細搜一下,這里就一帶而過了哈!8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

此時我們睡眠6s,包裝偏向鎖開啟成功!8gS28資訊網——每日最新資訊28at.com

我們來到序號2,開啟了偏向鎖,我們發現對象頭序號為:101。8gS28資訊網——每日最新資訊28at.com

「節點:從無鎖到偏向鎖切換的條件:JDK8中默認4s后開啟,JDK15需要手動開啟」。8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

來到序號3和4一起說吧,當我們進行synchronized加鎖時,對象的頭信息中會記錄上當前線程的id,下面再有加鎖的,直接判斷線程id是否一致,一致直接進入代碼塊。不一致后面再說!我們發現在序號4時,已經出了代碼塊,在此查詢加鎖的對象,信息依舊在,不會進行移除,這就是偏向,直到下一個線程把上一個替換掉!8gS28資訊網——每日最新資訊28at.com

代碼里循環了三次,對象都是一樣的!8gS28資訊網——每日最新資訊28at.com

「節點:在只有一個線程訪問代碼塊的時候,對象中會記錄當前線程id。」8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

「以上都是在一個線程來訪問的情況下」8gS28資訊網——每日最新資訊28at.com

來到序號5,我們新建了一個線程來進行加鎖。此時會判斷當前線程id和新線程id是否一致,不一致就會認為有競爭關系,會立刻切換為輕量級鎖。對象頭序號為:008gS28資訊網——每日最新資訊28at.com

「節點:當有兩個線程交替獲取鎖時,不存在同時競爭獲取鎖時。」8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

序號6和7一起說,我們讓上面序號5這個線程獲取鎖后睡眠3s,持續獲得鎖。在開啟一個新的線程去競爭獲取鎖,此時先進行自適應CAS自旋,一般10次后一直沒辦法獲取鎖,判定為激烈競爭關系。變為重量級鎖,序號7線程會進行放到阻塞隊列中。對象頭序號為:10。8gS28資訊網——每日最新資訊28at.com

經過睡眠后,序號6在此獲取對象的信息時,已經變為重量級鎖!8gS28資訊網——每日最新資訊28at.com

「節點:有兩個及其以上線程同時獲取鎖,且在自適應自旋范圍內沒有獲取到鎖」。8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

下面是代碼,大家可以在本地試一下!8gS28資訊網——每日最新資訊28at.com

/** * jvm默認延時4s自動開啟偏向鎖, * 可通過 -XX:BiasedLockingStartupDelay=0 * 取消延時如果不要偏向鎖,可通過-XX:-UseBiasedLocking = false * @author wangzhenjun * @date 2023/10/18 14:42 */public class LockUp {    @SneakyThrows    public static void main(String[] args) {        LockInfo lockInfo = new LockInfo();        System.out.println("1.無狀態:" + ClassLayout.parseInstance(lockInfo).toPrintable());        Thread.sleep(6000);        LockInfo lock = new LockInfo();        System.out.println("2.已經開啟了偏向鎖模式:" + ClassLayout.parseInstance(lock).toPrintable());        for (int i = 0; i < 3; i++) {            synchronized (lock) {                System.out.println("3.偏向鎖模式下,加鎖狀態:" + ClassLayout.parseInstance(lock).toPrintable());            }            System.out.println("4.鎖釋放了,加鎖狀態:" + ClassLayout.parseInstance(lock).toPrintable());        }        new Thread(() -> {            synchronized (lock) {                System.out.println("5.輕量級鎖,加鎖狀態:" + ClassLayout.parseInstance(lock).toPrintable());                System.out.println("睡眠3s");                try {                    Thread.sleep(3000);                } catch (InterruptedException e) {                    e.printStackTrace();                }                System.out.println("6.輕量級鎖=>重量級鎖,加鎖狀態:" + ClassLayout.parseInstance(lock).toPrintable());            }        }).start();        Thread.sleep(1000);        new Thread(() -> {            synchronized (lock) {                System.out.println("重量級鎖,加鎖狀態:" + ClassLayout.parseInstance(lock).toPrintable());            }        }).start();    }}

六、總結與拓展

經過實戰,我們知道了每一個的切換條件,可以在面試中好好地回答了。不至于面試官反問一下就不堅定了!8gS28資訊網——每日最新資訊28at.com

關于切換到重量級鎖后,有興趣的話,可以下載openJDK源碼去看一下關于hotspot/src/share/vm/runtime/objectMonitor.cpp和hotspot/src/share/vm/runtime/objectMonitor.hpp。8gS28資訊網——每日最新資訊28at.com

源碼下載地址:https://github.com/openjdk/jdk88gS28資訊網——每日最新資訊28at.com

objectMonitor.cpp:是 OpenJDK 中實現 Java 同步機制的核心部分,它負責管理對象監視器,確保多線程程序能夠正確協同工作,實現線程同步和等待/通知機制。8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

objectMonitor.hpp:主要用于定義對象監視器的接口和數據結構,為實際的對象監視器的實現提供了基礎。8gS28資訊網——每日最新資訊28at.com

8gS28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-17661-0.html不吃飯也要掌握的Synchronized鎖升級過程

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 一文讀懂Android架構演進歷程

下一篇: 一文帶你了解Spring Actuator

標簽:
  • 熱門焦點
  • 6月iOS設備好評榜:第一蟬聯榜首近一年

    作為安兔兔各種榜單里變化最小的那個,2023年6月的iOS好評榜和上個月相比沒有任何排名上的變化,僅僅是部分設備好評率的下降,長年累月的用戶評價和逐漸退出市場的老款機器讓這
  • Golang 中的 io 包詳解:組合接口

    io.ReadWriter// ReadWriter is the interface that groups the basic Read and Write methods.type ReadWriter interface { Reader Writer}是對Reader和Writer接口的組合,
  • 如何通過Python線程池實現異步編程?

    線程池的概念和基本原理線程池是一種并發處理機制,它可以在程序啟動時創建一組線程,并將它們置于等待任務的狀態。當任務到達時,線程池中的某個線程會被喚醒并執行任務,執行完任
  • 如何使用JavaScript創建一只圖像放大鏡?

    譯者 | 布加迪審校 | 重樓如果您曾經瀏覽過購物網站,可能遇到過圖像放大功能。它可以讓您放大圖像的特定區域,以便瀏覽。結合這個小小的重要功能可以大大改善您網站的用戶體驗
  • 使用Webdriver-manager解決瀏覽器與驅動不匹配所帶來自動化無法執行的問題

    1、前言在我們使用 Selenium 進行 UI 自動化測試時,常常會因為瀏覽器驅動與瀏覽器版本不匹配,而導致自動化測試無法執行,需要手動去下載對應的驅動版本,并替換原有的驅動,可能還
  • 為什么你不應該使用Div作為可點擊元素

    按鈕是為任何網絡應用程序提供交互性的最常見方式。但我們經常傾向于使用其他HTML元素,如 div span 等作為 clickable 元素。但通過這樣做,我們錯過了許多內置瀏覽器的功能。
  • 共享單車的故事講到哪了?

    來源丨海克財經與共享充電寶相差不多,共享單車已很久沒有被國內熱點新聞關照到了。除了一再漲價和用戶直呼用不起了。近日多家媒體再發報道稱,成都、天津、鄭州等地多個共享單
  • 騰訊蓋樓,字節拆墻

    來源 | 光子星球撰文 | 吳坤諺編輯 | 吳先之&ldquo;想重溫暴刷深淵、30+技能搭配暴搓到爽的游戲體驗嗎?一起上晶核,即刻暴打!&rdquo;曾憑借直播騰訊旗下代理格斗游戲《DNF》一
  • 三星折疊屏手機去年銷售近1000萬臺 今年目標定為1500萬

    7月29日消息,三星率先發力可折疊手機市場,在全球市場已經取得了非常亮眼的成績,接下來會進一步鞏固和擴大這一優勢。三星在推出Galaxy Z Flip5和Galax
Top 主站蜘蛛池模板: 泽州县| 光泽县| 重庆市| 临泽县| 舒城县| 昔阳县| 融水| 琼中| 磐安县| 陇西县| 江油市| 宜黄县| 海原县| 体育| 奉化市| 辉县市| 大荔县| 志丹县| 岳普湖县| 尚志市| 监利县| 利津县| 修武县| 溧水县| 剑阁县| 义马市| 灵璧县| 应城市| 徐水县| 香河县| 长寿区| 凤台县| 保定市| 台江县| 南康市| 万全县| 许昌市| 大邑县| 尚志市| 建瓯市| 湾仔区|