对象获取锁有三种途径:
1. 锁代码块
2. 锁方法
3. 锁静态方法
三种方式的字节码解读
1. 锁代码块
public class LockDemo {
Object object = new Object();
public void hello() {
synchronized (object) {
}
}
}
代码块: 通过monitorenter
和 monitorexit
来实现判断是否枷锁
第二个monitorexit
是防止我们中途中有其他的异常错误导致锁没有释放掉,所以这里才进行了第二次的释放锁
注意
一般来说 一个monitorenter 对两个 monitorexit,但是有时候也有特殊的情况,就是如果在代码中有异常的话那么就会只有一个monitorenter对应一个monitorexit,代码如下:
public class LockDemo {
Object object = new Object();
public void hello() {
synchronized (object) {
System.out.println("synchronized----");
throw new RuntimeException("我要抛出异常了..");
}
}
}
public void hello();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=3, locals=3, args_size=1
0: aload_0
1: getfield #3 // Field object:Ljava/lang/Object;
4: dup
5: astore_1
6: monitorenter// 这里是进入
7: getstatic #4 // Field java/lang/System.out:Ljava/io/PrintStream;
10: ldc #5 // String synchronized----
12: invokevirtual #6 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
15: new #7 // class java/lang/RuntimeException
18: dup
19: ldc #8 // String 我要抛出异常了..
21: invokespecial #9 // Method java/lang/RuntimeException."<init>":(Ljava/lang/String;)V
24: athrow
25: astore_2
26: aload_1
27: monitorexit//这里是释放, 注意这里只有这一次释放退出, 并没有两次释放
28: aload_2
29: athrow
Exception table:
from to target type
7 28 25 any
LineNumberTable:
line 11: 0
line 12: 7
line 13: 15
line 14: 25
StackMapTable: number_of_entries = 1
frame_type = 255 /* full_frame */
offset_delta = 25
locals = [ class com/lomonkey/synchronize/LockDemo, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
}
SourceFile: "LockDemo.java"
2. 锁方法
public class LockDemo {
public synchronized void hello() {
System.out.println("--hello");
}
}
public synchronized void hello();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=1, args_size=1
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String --hello
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 10: 0
line 11: 8
锁方法: 通过ACC_SYNCHRONIZED
来获取是否给方法枷锁
3. 锁静态方法:
public class LockDemo {
public static synchronized void hello() {
System.out.println("--hello");
}
}
public static synchronized void hello();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=2, locals=0, args_size=0
0: getstatic #2 // Field java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3 // String --hello
5: invokevirtual #4 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
LineNumberTable:
line 10: 0
line 11: 8
}
SourceFile: "LockDemo.java"
锁方法: 通过ACC_STATIC, ACC_SYNCHRONIZED
来表示是否给静态方法枷锁