java synchronized原理

synchronized是Java支持的锁。
我们熟知的几种用法有以下几种:

  • 普通同步方法,synchronized public void test(){}
  • 静态同步方法,synchronized public static void test(){}
  • 同步方法块,synchronized(this)

编写一个简单的Java测试代码如下,用javap生成一下反编译的代码,来看一下这3种情况在代码中是如何表示的

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...

你可能感兴趣的:(java)