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...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。