首頁 > Java > java教程 > 主體

Java Synchronized是什麼

WBOY
發布: 2023-05-14 08:28:05
轉載
1655 人瀏覽過

Synchronized是什麼

各位Java讀者,對於synchronized關鍵字並不陌生,在各種中間件源碼或JDK源碼中都能看到,對於不熟悉synchronized的讀者只知道在多線程中需要使用到synchronized關鍵字,知道synchronized能夠保證線程安全。

  • 稱之為:互斥鎖(同時只能一個執行緒執行,其他的執行緒將會等待)

  • 又稱之為:悲觀鎖定(同時只能一個執行緒執行,其他的執行緒將會等待)

  • JVM虛擬機幫你實現,開發者只需要使用synchronized關鍵字。

  • 使用時需要用一個物件當鎖的互斥量

  • #能夠保證一段程式碼(臨界區)的原子性 可見性。

從字節碼層面解析Synchronized關鍵字

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

class Demo1{
    // 互斥对象
    static Object object = new Object();
    // 竞争条件
    static int cout = 0;
    public static void main(String[] args) {
        // 互斥
        synchronized(object){
            // 以下是临界区
            cout++;
            System.out.println("synchronized");
        }
    }
}
登入後複製

光是從Java程式碼,我們並看不到啥東西,而Java程式編譯後是字節碼文件,所以我們解析一遍字節碼

常數池:
   #1 = Methodref          #7.#26         // java/lang/Object."":()V
    // java/lang/Object."":()V
    // java/lang/Object."":()V
    // java/18  // Demo1.object:Ljava/lang/Object;
   #3 = Fieldref           #8.#28         // Demo1.cout:I#努/ System .out:Ljava/io/PrintStream;
   #5 = String             #31            //同步作用##   #6 = Methodref .println:(Ljava/lang/String ; )V
   #7 = Class              #34            // java/lang/Object
    mo1
   #9 = Utf8               object
  #1 0 = Utf8 Ljava/lang/物件;
#11 = Utf8               cout
  #12 = Utf8               I
  #13 = Utf8     1           ()V
  #15 = Ut f8               代號








# #16 = Utf8               LineNumberTable
  #17 = Utf8               main
  #18 = U18         main
  #18 = U18                    StackMapTable
#20 = 類別             #36            //「 [Ljava/lang/String;"
  #21 = Class              #34            /// java / java/lang/Throwable
  #23 = Utf8               ;
  #24 = Utf8               SourceFile
  #25 = Utf8               Demo1.java##  #26 = Name/1  it>":()V
  #27 = NameAndType # 9:#10         // 物件:Ljava/lang/Object;
  #28 = NameAndType        #11:#12              // java/lang/System
#30 = NameAndType        #39:#40        // out:Ljava/io/PrintStream;
  #31 = Utf8        1             // java/io/PrintStream
  #33 = NameAndType #42:#43        // println:(Ljava/lang/String;)V
  #34 = Utf8               java/              [Ljava/lang / String;
  #37 = Utf8               java/lang/Throwable
  #38 = Utf8              java/lang/System# 1     out
  #40 = Utf8               Ljava/io/PrintStream;
#41 = Utf8               java/io/PrintStream
  #42 = Utf8               println##     0: getstatic     #2        // 從2號常數池取得靜態變量,壓入到操作數堆疊中                 
           3: dup        4: astore_1                // 將操作數堆疊的資料儲存到1號局部變數表中,給予釋放鎖定使用
         5: monitorenter 名詞開啟        6: getstatic     #3        // 從2號常數池拿到靜態變量,壓入操作數堆疊中
         9: iconst_1           9: iconst_1      10 iadd                    // 消耗兩個操作數堆疊的數據,相加,然後壓入堆疊頂部
        11: putstatic     #3        // 將操作數堆疊頂部的變數賦值與3號常數將4號常數池的物件壓入操作數堆疊
        17: ldc           #5        // 解析5號常數匣     // 執行println函數,消耗2個運算堆疊
        22: aload_1                 // 將1號局部變數表的資料壓入運算ized的字節碼層面實現
        24: goto          32        // 跳到32行。
        27: astore_2                // 可能有異常,但需要釋放鎖,所以將例外物件放入2號局部變數表##   1 1928: 1  入操作數堆疊的堆疊頂,供monitorexit指令使用
        29: monitorexit             // 可能有異常,但是要需要釋放鎖,不然死鎖了。
        30: aload_2                 // 將例外物件從2號局部變數表中壓入運算元堆疊的堆疊頂部
     # 31: 存在操作數 堆疊的頂部
         32: return                  // 函數回復中


以上是字節碼全解,其實很簡單,最終Synchronized關鍵字解析成字節為monitorenter和monitorexit字節碼指令,然後每次執行這2個字節碼指令前,把互斥物件壓入操作數棧供給monitorenter和monitorexit字節碼指令使用。

所以下一篇就是去Hotspot源碼解析monitorenter和monitorexit字節碼指令的詳細流程。

Synchronized與ReentrantLock的區別

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

相似點:

#都是互斥鎖的實作

不同點:

Synchronized基於JVM內部實現,ReentrantLock基於Java層面實作(但是ReentrantLock核心程式碼還是呼叫C 程式碼)。

    Synchronized在1.6以後經過優化,存在幾個不同級別的鎖,根據線程競爭的力度提升鎖的力度(俗稱鎖升級),更多的適合場景,而ReentrantLock在鎖力度選擇上略顯死板。
  • ReentrantLock雖然在鎖力度選擇上略顯死板,但是可以選擇公平和非公平,而Synchronized只能是非公平鎖定
  • ReentrantLock的條件等待隊列,可建立多個,高客製化。而Synchronized底層只有一個佇列。
  • ReentrantLock需要使用者手動開啟鎖定,手動釋放鎖定。而Synchronized關鍵字底層則透過字節碼自動實作
  • #

以上是Java Synchronized是什麼的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:yisu.com
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!