Synchronized的實(shí)現(xiàn)原理

Synchronized 鎖的兩種方式分別的針對(duì)方法的鎖和針對(duì)代碼塊的鎖。

代碼塊鎖

public class A {

    public void method() {
        synchronized (A.class) {
            System.out.println("lock method");
        }
        System.out.println("unlock method");
    }
    
    public static void main(String[] args) {
        new A().method();
    }
}

首先,我們用javap -c 來(lái)看下字節(jié)碼指令

$ javap -c A
Compiled from "A.java"
public class A {
  public A();
    Code:
       0: aload_0
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return

  public void method();
    Code:
       0: ldc           #2                  // class A
       2: dup
       3: astore_1
       4: monitorenter
       5: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
       8: ldc           #4                  // String lock method
      10: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      13: aload_1
      14: monitorexit
      15: goto          23
      18: astore_2
      19: aload_1
      20: monitorexit
      21: aload_2
      22: athrow
      23: getstatic     #3                  // Field java/lang/System.out:Ljava/io/PrintStream;
      26: ldc           #6                  // String unlock method
      28: invokevirtual #5                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
      31: return
    Exception table:
       from    to  target type
           5    15    18   any
          18    21    18   any

  public static void main(java.lang.String[]);
    Code:
       0: new           #2                  // class A
       3: dup
       4: invokespecial #7                  // Method "<init>":()V
       7: invokevirtual #8                  // Method method:()V
      10: return
}

我們可以從指令中看到兩個(gè)指令: monitorentermonitorexit
這兩個(gè)指令分別表示獲得對(duì)象鎖和釋放對(duì)象鎖

當(dāng)一個(gè)線程在執(zhí)行monitorenter指令時(shí),會(huì)嘗試獲得對(duì)象鎖(鎖的幾種類(lèi)型),如果獲取成功,則執(zhí)行代碼塊中的內(nèi)容,如果獲取失敗,則等待釋放鎖。synchronized代碼塊執(zhí)行完后,執(zhí)行monitorexit指令,釋放monitor對(duì)象鎖。

詳細(xì)描述如下
monitorenter:
Each object is associated with a monitor. A monitor is locked if and only if it has an owner. The thread that executes monitorenter attempts to gain ownership of the monitor associated with objectref, as follows:
? If the entry count of the monitor associated with objectref is zero, the thread enters the monitor and sets its entry count to one. The thread is then the owner of the monitor.
? If the thread already owns the monitor associated with objectref, it reenters the monitor, incrementing its entry count.
? If another thread already owns the monitor associated with objectref, the thread blocks until the monitor's entry count is zero, then tries again to gain ownership.

monitorexit:
The thread that executes monitorexit must be the owner of the monitor associated with the instance referenced by objectref.
The thread decrements the entry count of the monitor associated with objectref. If as a result the value of the entry count is zero, the thread exits the monitor and is no longer its owner. Other threads that are blocking to enter the monitor are allowed to attempt to do so.

大概含義是每個(gè)對(duì)象都有一個(gè)對(duì)象鎖,這個(gè)對(duì)象鎖的enter count是0,就可以讓多個(gè)線程搶占,如果被某個(gè)線程搶占成功,則enter count加1,當(dāng)執(zhí)行monitorexit的時(shí)候,這個(gè)enter count減一,當(dāng)被減為0時(shí),表明該線程釋放鎖。
同時(shí),如果一個(gè)線程成功獲取到monitor,可以多次執(zhí)行monitorenter,enter count 多次加1,釋放時(shí)也多次執(zhí)行monitorexit使得enter count 減為0
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容