synchronized底层字节码实现
同步代码块
同步代码块实现使用的是monitorenter和monitorexit命令 进行进入和退出(退出命令会有多条 以防止程序抛出异常的时候锁无法进行释放)
代码示例:
Code:
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 --------hello
12: invokevirtual #6 // 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
普通同步方法
普通同步方法使用的是同步标识ACC_SYNCHRONIZED进行方法的标明
调用指令将会检查方法的ACC_SYNCHRONIZED访问标志是否被设置.如果设置了,执行线程会将先持有monitor然后在执行方法,最后在方法完成(或者是抛出异常)时释放monitor
代码示例:
public synchronized void m2();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED
Code:
stack=0, locals=1, args_size=1
0: return
LineNumberTable:
line 14: 0
LocalVariableTable:
Start Length Slot Name Signature
0 1 0 this Ljuc/lock/LockByteCodeDemo;
静态同步方法
静态同步方法 用 ACC_STATIC, ACC_SYNCHRONIZED 两个访问标志标识该方法是静态同步方法
代码示例:
public static synchronized void m2();
descriptor: ()V
flags: ACC_PUBLIC, ACC_STATIC, ACC_SYNCHRONIZED
Code:
stack=0, locals=0, args_size=0
0: return
LineNumberTable:
line 18: 0
synchronized到底锁的是什么(是管程)
为什么每个对象都可以有锁
因为Java所有类的基类就是 Object类 Object类在jdk源码的c++文件中有对象ObjectMonitor 这个对象有一些属性值记录了当前持有对象锁的线程和一些其他属性 是通过基类的c++对象代码去扩展的这个锁属性 每个对象都天生带着一个对象监视器
重要属性示意图如下:
synchronized的jvm实现
synchronized必须作用于某个对象中 所以Java在对象的头文件存储了锁的相关信息. 锁升级功能主要依赖于MarkWord中的锁标志位和释放偏向锁标志位.
示例图如下