亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

關(guān)于Java鎖性能提高(鎖升級)機制的總結(jié)

 更新時間:2022年05月05日 15:19:41   作者:qq838642798  
這篇文章主要介紹了關(guān)于Java鎖性能提高(鎖升級)機制的總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

Java鎖性能提高機制

鎖的使用很難避免,如何盡量提高鎖的性能就顯得比較重要了

鎖偏向

所謂的偏向鎖是指在對象實例的Mark Word(說白了就是對象內(nèi)存中的開頭幾個字節(jié)保留的信息,如果把一個對象序列化后明顯可以看見開頭的這些信息),為了在線程競爭不激烈的情況下,減少加鎖及解鎖的性能損耗(輕量級鎖涉及多次CAS操作)在Mark Word中有保存這上次使用這個對象鎖的線程ID信息,如果這個線程再次請求這個對象鎖,那么只需要讀取該對象上的Mark Word的偏向鎖信息(也就是線程id)跟線程本身的id進行對比,如果是同一個id就直接認為該id獲得鎖成功,而不需要在進行真正的加解鎖操作。

其實說白了就是你上次來過了,這次又來,并且在這兩次之間沒有其他人來過,對于這個線程來說,鎖對象的資源隨便用都是安全的。這次用緩存來換取性能的做法,不過偏向鎖在鎖競爭不激烈的情景下使用才能獲取比較高的效率。當使用CAS競爭偏向鎖失敗,表示競爭比較激烈,偏向鎖升級為輕量級鎖。

輕量級鎖

所謂輕量級鎖是比偏向鎖更耗資源的鎖,實現(xiàn)機制是,線程在競爭輕量級鎖前,在線程的棧內(nèi)存中分配一段空間作為鎖記錄空間(就是輕量級鎖對應(yīng)的對象的對象頭的字段的拷貝),拷貝好后,線程通過CAS去競爭這個對象鎖,試圖把對象的對象頭子段改成指向所記錄空間,如果成功則說明獲取輕量級鎖成功,如果失敗,則進入自旋(說白了就是循環(huán))取試著獲取鎖。如果自旋到一定次數(shù)還是不能獲取到鎖,則進入重量級鎖。

自旋鎖

說白了就是獲取鎖失敗后,為了避免直接讓線程進入阻塞狀態(tài)而采取的循環(huán)一定次數(shù)去試著獲取鎖的行為。(線程進入阻塞狀態(tài)和退出阻塞狀態(tài)是涉及到操作系統(tǒng)管理層面的,需要從用戶態(tài)進入內(nèi)核態(tài),非常消耗系統(tǒng)資源),為什么能這樣做呢,是因為試驗證明,鎖的持有時間一般是非常短的,所以一般多次嘗試就能競爭到鎖。

重量級鎖

所謂的重量級鎖,其實就是最原始和最開始java實現(xiàn)的阻塞鎖。在JVM中又叫對象監(jiān)視器。

這時的鎖對象的對象頭字段指向的是一個互斥量,所有線程競爭重量級鎖,競爭失敗的線程進入阻塞狀態(tài)(操作系統(tǒng)層面),并且在鎖對象的一個等待池中等待被喚醒,被喚醒后的線程再次去競爭鎖資源。

小結(jié):

所謂的鎖升級,其實就是從偏向鎖à輕量級鎖(自旋鎖)à重量級鎖,之前一直被這幾個概念困擾,網(wǎng)上的 文章解釋的又不通俗易懂,其實說白了,一切一切的開始源于java對synchronized同步機制的性能優(yōu)化,最原始的synchronized同步機制是直接跳過前幾個步驟,直接進入重量級鎖的,而重量級鎖因為需要線程進入阻塞狀態(tài)(從用戶態(tài)進入內(nèi)核態(tài))這種操作系統(tǒng)層面的操作非常消耗資源,這樣的話,synchronized同步機制就顯得很笨重,效率不高。

那么為了解決這個問題,java才引入了偏向鎖,輕量級鎖,自旋鎖這幾個概念。

拿這幾個鎖有何優(yōu)化呢?網(wǎng)上也沒有通俗易懂的解釋,其實說白了就是,偏向鎖是為了避免CAS操作,盡量在對比對象頭就把加鎖問題解決掉,只有沖突的情況下才指向一次CAS操作,而輕量級鎖和自旋鎖呢,其實兩個是一體使用的,為的是盡量避免線程進入內(nèi)核的阻塞狀態(tài),這對性能非常不利,試圖用CAS操作和循環(huán)把加鎖問題解決掉,而重量級鎖是最終的無奈解決方案,說白了就是能通過內(nèi)存讀取判斷解決加速問題優(yōu)于〉通過CAS操作和空循環(huán)優(yōu)于〉CPU阻塞,喚醒線程。

Java鎖升級簡述

什么是鎖:在并發(fā)環(huán)境下,多線程針對同一個資源進行爭搶,可能會導(dǎo)致數(shù)據(jù)出現(xiàn)異常,為了解決這個問題,就引入了鎖機制。通過鎖對資源進行鎖定。

在JVM當中,寄存器、虛擬機棧、本地方法棧是線程獨享(安全)的。但是Java堆(保存所有的Java對象和數(shù)組)、方法區(qū)、運行時常量池是線程共享的,就有可能出現(xiàn)線程安全問題。每個object對象都有一把鎖,這個鎖在對象頭中,記錄著這個對象在被哪個線程占用著。

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

Java的對象分為三個部分:對象頭、實例數(shù)據(jù)、對齊填充字節(jié)。

對象頭存放了對象本身的運行時信息。對象頭包含了兩部分:Mark Word和ClassPointer。相對于實際數(shù)據(jù),對象頭屬于一些額外的內(nèi)存開銷。因此被設(shè)計的極小以提升效率。其中,Mark Word中,就包含了鎖信息。

鎖狀態(tài)25bit4bit1bit2bit
23bit2bit是否偏向鎖鎖標志位
無鎖對象的hashCode分代年齡001
偏向鎖線程idEpoch分代年齡101
輕量級鎖指向棧中鎖記錄的指針00
重量級鎖指向重量級鎖的指針10
GC標記11

Mark Word(32位為例)

對象內(nèi)存存在一把鎖,鎖信息放在了對象頭的Mark Word當中。在最后兩位中,代表了鎖標志位:無鎖、偏向鎖、輕量級鎖、重量級鎖。

synchronized關(guān)鍵字

synchronized關(guān)鍵字可以用來同步線程,synchronized被編譯后,會生成monitorenter,monitorexit兩個字節(jié)碼指令。JVM以此來進行線程同步。

monitor

 monitor即為同步監(jiān)視器,一個線程進入了monitor,其他線程只能夠等待,當且只有這個線程退出,其他線程才有機會競爭到所資源進行執(zhí)行。

Entry Set中聚集了一些想要進入Monitor的線程,它們處于waiting狀態(tài),假設(shè)某個名為A線程成功進入了Monitor,那么它就處于active狀態(tài)。假設(shè)此時A線程執(zhí)行途中,遇到一個判斷條件,需要它暫時讓出執(zhí)行權(quán),那么它將進入wait set,狀態(tài)也被標記為waiting。這時entry set中的線程就有機會進入monitor,假設(shè)一個線程B成功進入并且順利完成,那么它可以通過notify的形式來喚醒wait set中的線程A,讓線程A再次進入Monitor,執(zhí)行完成后便退出。

這就是synchronized的同步機制,但是synchronized可能存在性能問題,因為monitor是依賴于操作系統(tǒng)的Mutex Lock來實現(xiàn)的,Java線程事實上是對操作系統(tǒng)線程的映射,所以每當掛起或喚醒一個線程都要切換到操作系統(tǒng)的內(nèi)核態(tài),這個操作是比較重量級的。在一些情況下,甚至切換時間本身就會超出線程執(zhí)行任務(wù)的時間,這樣的話,使用synchronized將會對程序的性能產(chǎn)生影響。

從Java6開始,synchronized關(guān)鍵字就進行了優(yōu)化,引入了“偏向鎖”,“輕量級鎖”,所以鎖共有四種狀態(tài),分別為:無鎖、偏向鎖、輕量級鎖、重量級鎖。

鎖的四種狀態(tài)

無鎖

  • 無鎖顧名思義就是沒有對資源進行鎖定,所有線程都能夠訪問同一資源。在出現(xiàn)資源競爭的情況下,不想對資源進行鎖定,但是還是想通過某種手段進行多線程的控制。假如有一個累計值,我們不想通過鎖定資源的方式進行限制,但是想控制只有一個線程能修改成功的話,就可以通過CAS操作(可以看AutomaticInteger中對unsafe類的操作)。但是當出現(xiàn)循環(huán)的時候,某個時間的cpu占用率會變得很高,而且可能出現(xiàn)ABA問題(通過版本號解決)。

偏向鎖

  • 當我們開始為對象進行加鎖,假如某對象被加鎖了,但在實際運行的時候,只有一條線程會獲取這個對鎖,那么我們最理想的方式,是不要通過系統(tǒng)狀態(tài)切換,也不通過CAS獲取鎖,因為那樣或多或少還是消耗了一些資源。我們設(shè)想的是最好對象能夠認識這個線程,只要是這個線程過來,那么對象就直接把鎖交出去。我們可以認為這個對象偏愛這個線程,所以被稱為“偏向鎖”。
  • 那么偏向鎖是怎么實現(xiàn)的呢?在Mark Word中,當鎖標志為是01,那么判斷倒數(shù)第三個bit是否為1,如果是1,那么代表當前對象的鎖狀態(tài)為偏向鎖,于是再去讀Mark Word的前23個bit,這23個bit就是線程ID,通過線程ID來確認想要獲得對象鎖的線程是不是之前所記錄的線程ID。

輕量級鎖

  • 假如情況發(fā)生了變化,對象發(fā)現(xiàn)目前不只有一個線程,而是有多個線程正在競爭鎖,那么偏向鎖將會升級為輕量級鎖。Mark
  • Word發(fā)生變化,指向棧中Lock Record的指針。

重量級鎖

  • 倘若在輕量級鎖的情況下,線程自旋次數(shù)過多,這個時候就會從輕量級鎖轉(zhuǎn)換成為重量級鎖。Mark Word再次發(fā)生變化,指向重量級鎖的指針。這個時候,其他線程試圖獲取鎖時都會被阻塞,只有持有鎖的線程釋放鎖之后才會喚醒這些線程。 

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • java 二維數(shù)組矩陣乘法的實現(xiàn)方法

    java 二維數(shù)組矩陣乘法的實現(xiàn)方法

    java 二維數(shù)組矩陣乘法的實現(xiàn)方法,需要的朋友可以參考一下
    2013-03-03
  • 深入解析Java的Servlet過濾器的原理及其應(yīng)用

    深入解析Java的Servlet過濾器的原理及其應(yīng)用

    這篇文章主要介紹了深入解析Java的Servlet過濾器的原理及應(yīng)用,Java編寫的Servlet通常是一個與網(wǎng)頁一起作用于瀏覽器客戶端的程序,需要的朋友可以參考下
    2016-01-01
  • MyBatis獲取自動生成的(主)鍵值的方法

    MyBatis獲取自動生成的(主)鍵值的方法

    本文主要介紹了MyBatis獲取自動生成的(主)鍵值的方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-04-04
  • 利用Maven入手Spring Boot第一個程序詳解

    利用Maven入手Spring Boot第一個程序詳解

    這篇文章主要給大家介紹了關(guān)于如何利用Maven入手Spring Boot第一個程序的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2018-02-02
  • Springboot使用jsp具體案例解析

    Springboot使用jsp具體案例解析

    這篇文章主要介紹了Springboot使用jsp具體案例解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Spring Boot使用和配置Druid

    Spring Boot使用和配置Druid

    本篇文章主要介紹了Spring Boot使用和配置Druid,Druid號稱是Java語言中最好的數(shù)據(jù)庫連接池,并且能夠提供強大的監(jiān)控和擴展功能
    2017-04-04
  • Java SpringBoot容器注入對象詳解

    Java SpringBoot容器注入對象詳解

    本文通過實例代碼給大家詳解了springboot獲取ioc容器中注入的bean問題,非常不錯,具有一定的參考借鑒價值,需要的朋友參考下吧
    2021-09-09
  • 一次踩坑記錄 @valid注解不生效 排查過程

    一次踩坑記錄 @valid注解不生效 排查過程

    這篇文章主要介紹了一次踩坑記錄 @valid注解不生效 排查過程,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-06-06
  • Spring AI實現(xiàn)智能聊天模型

    Spring AI實現(xiàn)智能聊天模型

    通過本文的介紹,我們深入了解了Spring AI項目的優(yōu)勢和特性,以及在實際應(yīng)用中的快速實戰(zhàn)示例,Spring AI作為一個高度抽象化的人工智能應(yīng)用程序開發(fā)框架,為開發(fā)者提供了便捷的模型支持、靈活的功能模塊交換和優(yōu)化能力
    2024-11-11
  • java?spring?validation?自動、手動校驗

    java?spring?validation?自動、手動校驗

    HibernateValidator簡化了Java開發(fā)中的參數(shù)校驗過程,提供自動和手動兩種校驗方式,通過引入相關(guān)依賴并使用@Validated注解,可以實現(xiàn)自動校驗,手動校驗則需要使用ValidatorUtils類,此方法有效減少代碼重復(fù),提高開發(fā)效率
    2024-09-09

最新評論