最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java Synchronized字節(jié)碼層分析體驗

 更新時間:2023年04月10日 09:27:19   作者:程序員李哈  
這篇文章主要介紹了Java Synchronized字節(jié)碼層分析,synchronized關(guān)鍵字解決了多個線程之間的資源同步性,synchronized關(guān)鍵字保證了它修飾的方法或者代碼塊任意時刻只有一個線程在訪問

Synchronized是什么

各位Java讀者,對于synchronized關(guān)鍵字并不陌生,在各種中間件源碼或者JDK源碼中都能看到,對于不熟悉synchronized的讀者只知道在多線程中需要使用到synchronized關(guān)鍵字,知道synchronized能夠保證線程安全,那么本篇文章帶領(lǐng)各位讀者對synchronized有一個認(rèn)識。

  • 稱之為:互斥鎖(同時只能一個線程執(zhí)行,其他的線程將會等待)
  • 又稱之為:悲觀鎖(同時只能一個線程執(zhí)行,其他的線程將會等待)
  • JVM虛擬機(jī)幫你實現(xiàn),開發(fā)者只需要使用synchronized關(guān)鍵字即可。
  • 使用時需要用一個對象當(dāng)鎖的互斥量
  • 能夠保證一段代碼(臨界區(qū))的原子性+可見性。
  • 等等......

從字節(jié)碼層面解析Synchronized關(guān)鍵字

從案例入手,最合適不過。

class Demo1{
    // 互斥對象
    static Object object = new Object();
    // 競爭條件
    static int cout = 0;
    public static void main(String[] args) {
        // 互斥
        synchronized(object){
            // 以下是臨界區(qū)
            cout++;
            System.out.println("synchronized");
        }
    }
}

僅僅從Java代碼,我們并不能看出啥東西,而Java程序編譯后是字節(jié)碼文件,所以我們解析一遍字節(jié)碼

Constant pool:
   #1 = Methodref          #7.#26         // java/lang/Object."<init>":()V
   #2 = Fieldref           #8.#27         // Demo1.object:Ljava/lang/Object;
   #3 = Fieldref           #8.#28         // Demo1.cout:I
   #4 = Fieldref           #29.#30        // java/lang/System.out:Ljava/io/PrintStream;
   #5 = String             #31            // synchronized
   #6 = Methodref          #32.#33        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #7 = Class              #34            // java/lang/Object
   #8 = Class              #35            // Demo1
   #9 = Utf8               object
  #10 = Utf8               Ljava/lang/Object;
  #11 = Utf8               cout
  #12 = Utf8               I
  #13 = Utf8               <init>
  #14 = Utf8               ()V
  #15 = Utf8               Code
  #16 = Utf8               LineNumberTable
  #17 = Utf8               main
  #18 = Utf8               ([Ljava/lang/String;)V
  #19 = Utf8               StackMapTable
  #20 = Class              #36            // "[Ljava/lang/String;"
  #21 = Class              #34            // java/lang/Object
  #22 = Class              #37            // java/lang/Throwable
  #23 = Utf8               <clinit>
  #24 = Utf8               SourceFile
  #25 = Utf8               Demo1.java
  #26 = NameAndType        #13:#14        // "<init>":()V
  #27 = NameAndType        #9:#10         // object:Ljava/lang/Object;
  #28 = NameAndType        #11:#12        // cout:I
  #29 = Class              #38            // java/lang/System
  #30 = NameAndType        #39:#40        // out:Ljava/io/PrintStream;
  #31 = Utf8               synchronized
  #32 = Class              #41            // java/io/PrintStream
  #33 = NameAndType        #42:#43        // println:(Ljava/lang/String;)V
  #34 = Utf8               java/lang/Object
  #35 = Utf8               Demo1
  #36 = Utf8               [Ljava/lang/String;
  #37 = Utf8               java/lang/Throwable
  #38 = Utf8               java/lang/System
  #39 = Utf8               out
  #40 = Utf8               Ljava/io/PrintStream;
  #41 = Utf8               java/io/PrintStream
  #42 = Utf8               println
  #43 = Utf8               (Ljava/lang/String;)V
         0: getstatic     #2        // 從2號常量池中拿到靜態(tài)變量,壓入到操作數(shù)棧中                  
         3: dup                     // 把操作數(shù)棧棧頂?shù)膶ο筚x值一份
         4: astore_1                // 將操作數(shù)棧的數(shù)據(jù)保存到1號局部變量表中,給釋放鎖使用
         5: monitorenter            // 互斥鎖開啟,也是synchronized的字節(jié)碼層面實現(xiàn)
         6: getstatic     #3        // 從2號常量池中拿到靜態(tài)變量,壓入到操作數(shù)棧中
         9: iconst_1                // 將常量1壓入到操作數(shù)棧中
        10: iadd                    // 消耗兩個操作數(shù)棧的數(shù)據(jù),相加,然后壓入棧頂
        11: putstatic     #3        // 將操作數(shù)棧棧頂?shù)淖兞抠x值給3號常量池
        14: getstatic     #4        // 將4號常量池的對象壓入操作數(shù)棧
        17: ldc           #5        // 解析5號常量池的符號,拿到字符串常量"synchronized"     
        19: invokevirtual #6        // 執(zhí)行println函數(shù),消耗2個操作數(shù)棧
        22: aload_1                 // 將1號局部變量表的數(shù)據(jù)壓入操作數(shù)棧
        23: monitorexit             // 互斥鎖的結(jié)束,也是synchronized的字節(jié)碼層面實現(xiàn)
        24: goto          32        // 跳轉(zhuǎn)到32行。
        27: astore_2                // 可能存在異常,但是要需要釋放鎖,所以把異常對象放入2號局部變量表
        28: aload_1                 // 把1號局部變量表數(shù)據(jù)壓入操作數(shù)棧的棧頂,供monitorexit指令使用
        29: monitorexit             // 可能存在異常,但是要需要釋放鎖,不然死鎖了。
        30: aload_2                 // 把異常對象從2號局部變量表中壓入操作數(shù)棧的棧頂
        31: athrow                  // 存在異常拋出
        32: return                  // 函數(shù)返回

以上是字節(jié)碼全解,其實很簡單,最終Synchronized關(guān)鍵字解析成字節(jié)為monitorenter和monitorexit字節(jié)碼指令,然后每次執(zhí)行這2個字節(jié)碼指令前,把互斥對象壓入操作數(shù)棧供給monitorenter和monitorexit字節(jié)碼指令使用。

所以下一篇就是去Hotspot源碼中解析monitorenter和monitorexit字節(jié)碼指令的詳細(xì)流程。

Synchronized與ReentrantLock的區(qū)別

這是一道很常見的面試題,面試被問到的頻率非常高

相似點:

都是互斥鎖的實現(xiàn)

不同點:

  • Synchronized基于JVM內(nèi)部實現(xiàn),ReentrantLock基于Java層面實現(xiàn)(但是ReentrantLock核心代碼還是調(diào)用C++代碼)。
  • Synchronized在1.6以后經(jīng)過優(yōu)化,存在幾個不同級別的鎖,根據(jù)線程競爭的力度提升鎖的力度(俗稱鎖升級),更多的適合場景,而ReentrantLock在鎖力度選擇上略顯死板。
  • ReentrantLock雖然在鎖力度選擇上略顯死板,但是可以選擇公平和非公平,而Synchronized只能是非公平鎖
  • ReentrantLock的條件等待隊列,可創(chuàng)建多個,高定制化。而Synchronized底層只有一個隊列。
  • ReentrantLock需要用戶手動開啟鎖,手動釋放鎖。而Synchronized關(guān)鍵字底層通過字節(jié)碼自動實現(xiàn)

到此這篇關(guān)于Java Synchronized字節(jié)碼層分析體驗的文章就介紹到這了,更多相關(guān)Java Synchronized內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解java安全編碼指南之可見性和原子性

    詳解java安全編碼指南之可見性和原子性

    java類中會定義很多變量,有類變量也有實例變量,這些變量在訪問的過程中,會遇到一些可見性和原子性的問題。這里我們來詳細(xì)了解一下怎么避免這些問題。
    2021-06-06
  • Java超詳細(xì)分析抽象類和接口的使用

    Java超詳細(xì)分析抽象類和接口的使用

    在類中沒有包含足夠的信息來描繪一個具體的對象,這樣的類稱為抽象類,接口是Java中最重要的概念之一,它可以被理解為一種特殊的類,不同的是接口的成員沒有執(zhí)行體,是由全局常量和公共的抽象方法所組成,本文給大家介紹Java抽象類和接口,感興趣的朋友一起看看吧
    2022-04-04
  • 解析iReport自定義行數(shù)分頁的操作方法

    解析iReport自定義行數(shù)分頁的操作方法

    ireport默認(rèn)都是自動分頁數(shù)據(jù)超出頁面長度就會自動分到下一頁,但有時候業(yè)務(wù)需要一頁只顯示固定幾行這時候就需要自定義條數(shù)了。下面看具體操作吧
    2021-10-10
  • 微信開發(fā)--自定義菜單查詢返碼亂碼的解決方法

    微信開發(fā)--自定義菜單查詢返碼亂碼的解決方法

    本篇文章主要介紹了微信開發(fā)--自定義菜單查詢返碼亂碼的解決方法,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • java用兩個例子充分闡述多態(tài)的可拓展性介紹

    java用兩個例子充分闡述多態(tài)的可拓展性介紹

    下面小編就為大家?guī)硪黄猨ava用兩個例子充分闡述多態(tài)的可拓展性介紹。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-06-06
  • 基于SpringBoot的Dubbo泛化調(diào)用的實現(xiàn)代碼

    基于SpringBoot的Dubbo泛化調(diào)用的實現(xiàn)代碼

    這篇文章主要介紹了基于SpringBoot的Dubbo泛化調(diào)用的實現(xiàn),從泛化調(diào)用實現(xiàn)的過程來看,我們可以對自己提供所有服務(wù)進(jìn)行測試,不需要引入調(diào)用的接口,減少代碼的侵入,需要的朋友可以參考下
    2022-04-04
  • java 如何判斷是否是26個英文字母

    java 如何判斷是否是26個英文字母

    這篇文章主要介紹了java 如何判斷是否是26個英文字母的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-01-01
  • java 通過 SmbFile 類操作共享文件夾的示例

    java 通過 SmbFile 類操作共享文件夾的示例

    這篇文章主要介紹了java 通過 SmbFile 類操作共享文件夾,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-02-02
  • MyBatis?動態(tài)SQL使用及原理

    MyBatis?動態(tài)SQL使用及原理

    這篇文章主要為大家介紹了MyBatis動態(tài)SQL使用及原理的學(xué)習(xí)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • 淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS)

    淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS)

    本篇文章主要介紹了淺談spring-boot 允許接口跨域并實現(xiàn)攔截(CORS),具有一定的參考價值,有興趣的可以了解一下
    2017-08-08

最新評論

商洛市| 修武县| 耒阳市| 七台河市| 横峰县| 阿巴嘎旗| 东乡县| 余干县| 民丰县| 清苑县| 宣化县| 望江县| 南乐县| 龙山县| 丹江口市| 赤壁市| 南京市| 昆明市| 龙井市| 淮北市| 佛坪县| 余干县| 嫩江县| 弥勒县| 肥乡县| 峡江县| 栾川县| 南投县| 新建县| 行唐县| 石家庄市| 五常市| 漯河市| 十堰市| 邹城市| 齐河县| 枣庄市| 乐清市| 宜宾县| 西宁市| 确山县|