synchronized 是并发中常用的关键字,用于方法或者是代码的同步,也是常见的面试点
使用javap -verbose -p Clazz 命令查看字节码
不带synchronized的方法
private void setX(int);
descriptor: (I)V
flags: (0x0002) ACC_PRIVATE
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: putfield #2 // Field x:I
5: return
LineNumberTable:
line 9: 0
line 10: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/compass/spring_lecture/binarycode/SynchronizedCode;
0 6 1 x I
加上synchronized的方法
private synchronized void setX(int);
descriptor: (I)V
flags: (0x0022) ACC_PRIVATE, ACC_SYNCHRONIZED
Code:
stack=2, locals=2, args_size=2
0: aload_0
1: iload_1
2: putfield #2 // Field x:I
5: return
LineNumberTable:
line 9: 0
line 10: 5
LocalVariableTable:
Start Length Slot Name Signature
0 6 0 this Lcom/compass/spring_lecture/binarycode/SynchronizedCode;
0 6 1 x I
修饰的是方法,并不是代码块并不会体现monitorenter及monitorexit
可重入锁,一个线程获取锁之后可以继续获取,获取N次必须释放N次 自带计数器 标记进入和出来的次数。
其他线程阻塞、或者使用自旋锁(占用cpu资源)。
是一个重量级的锁,新版本的jdk对synchronized已经做了优化,建议使用Lock或ReentrantLock
source code:
private void test(){
synchronized (object){
System.out.println("welcome");
}
}
反编译:
private void test();
descriptor: ()V
flags: (0x0002) ACC_PRIVATE
Code:
stack=2, 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 #5 // Field java/lang/System.out:Ljava/io/PrintStream;
10: ldc #6 // String welcome
12: invokevirtual #7 // Method java/io/PrintStream.println:(Ljava/lang/String;)V
15: aload_1
16: monitorexit //正常的退出
----------------------------------
17: goto 25
20: astore_2
21: aload_1
22: monitorexit //异常的退出
23: aload_2
24: athrow
25: return
Exception table:
from to target type
7 17 20 any
20 23 20 any
LineNumberTable:
line 17: 0
line 19: 7
line 21: 15
line 23: 25
LocalVariableTable:
Start Length Slot Name Signature
0 26 0 this Lcom/compass/spring_lecture/binarycode/SynchronizedCode;
StackMapTable: number_of_entries = 2
frame_type = 255 /* full_frame */
offset_delta = 20
locals = [ class com/compass/spring_lecture/binarycode/SynchronizedCode, class java/lang/Object ]
stack = [ class java/lang/Throwable ]
frame_type = 250 /* chop */
offset_delta = 4
静态synchronized方法:
private synchronized static void test2() {
}
private static synchronized void test2();
descriptor: ()V
flags: (0x002a) ACC_PRIVATE, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=0, locals=0, args_size=0
0: return
LineNumberTable:
line 28: 0
网友评论