java synchronized原理

synchronized是Java支持的鎖。
咱們熟知的幾種用法有如下幾種:html

  • 普通同步方法,synchronized public void test(){}
  • 靜態同步方法,synchronized public static void test(){}
  • 同步方法塊,synchronized(this)

編寫一個簡單的Java測試代碼以下,用javap生成一下反編譯的代碼,來看一下這3種狀況在代碼中是如何表示的java

package leetcode.thread;

public class ThreadTest {

    public Object lock = new Object();

    public void first(Runnable printFirst) throws InterruptedException {
        // 代碼塊
        synchronized (lock) {
            printFirst.run();
            lock.notifyAll();
        }
    }

    synchronized public void test(){
        System.out.println("test");
    }

    synchronized public static void test1(){
        System.out.println("test1");
    }
}

反編譯的代碼太多,先看下同步代碼塊的代碼:編程

public void first(java.lang.Runnable) throws java.lang.InterruptedException;
    descriptor: (Ljava/lang/Runnable;)V
    flags: ACC_PUBLIC
    Code:
      stack=2, locals=4, args_size=2
         0: aload_0
         1: getfield      #3                  // Field lock:Ljava/lang/Object;
         4: dup
         5: astore_2
         6: monitorenter
         7: aload_1
         8: invokeinterface #4,  1            // InterfaceMethod java/lang/Runnable.run:()V
        13: aload_0
        14: getfield      #3                  // Field lock:Ljava/lang/Object;
        17: invokevirtual #5                  // Method java/lang/Object.notifyAll:()V
        20: aload_2
        21: monitorexit
        22: goto          30
        25: astore_3
        26: aload_2
        27: monitorexit
        28: aload_3
        29: athrow
        30: return
      Exception table:
         from    to  target type
             7    22    25   any
            25    28    25   any
      LineNumberTable:
        line 9: 0
        line 10: 7
        line 11: 13
        line 12: 20
        line 13: 30
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 25
          locals = [ class leetcode/thread/ThreadTest, class java/lang/Runnable, class java/lang/Object ]
          stack = [ class java/lang/Throwable ]
        frame_type = 250 /* chop */
          offset_delta = 4
    Exceptions:
      throws java.lang.InterruptedException
SourceFile: "ThreadTest.java"

首先看方法first,你能夠看到在同步代碼塊的位置,有一個monitorenter指令,在結束位置,有一個monitorexit指令。在Java併發編程實踐這本書中介紹說,JVM是基於進入和退出Monitor對象來實現同步方法和同步代碼塊,關於這個monitor,其實在oracle的文檔裏面都介紹過的,這個原本的名字是intrinsic lock or monitor lock,這個通常被人稱做monitor,Java的同步少不了這個實體。oracle的文檔中還有一句話,’Every object has an intrinsic lock associated with it‘,也就是說這個東西是每一個對象都有的。
接下來介紹這兩個指令,第一個,monitorenter,這個的做用是‘Enter monitor for object’,線程執行這個指令就是爲了拿到對象所對應的monitor的全部權。monitorexit的話,就意味着釋放。併發

參考:
https://docs.oracle.com/javas...
https://docs.oracle.com/javas...oracle

相關文章
相關標籤/搜索