JVM字节码分析--Synchronized关键字底层实现

JVM字节码分析--Synchronized关键字底层实现

一、代码块级别的 synchronized

一个代码块加synchronized关键字的例子:

private Object lock = new Object();
public void test() {
    synchronized (lock) {
        foo();
    }
}

public void foo() { }

字节码反编译:

public void test();
    Code:
       0: aload_0
       1: getfield      #3                  // private Object lock = new Object();
       4: dup
       5: astore_1
       
       6: monitorenter
       
       7: aload_0
       8: invokevirtual #4                  // Method foo:()V
       
      11: aload_1
      12: monitorexit
      13: goto          21
      
      16: astore_2
      17: aload_1
      18: monitorexit
      19: aload_2
      20: athrow
      21: return
    Exception table:
       from    to  target type
           7    13    16   any
          16    19    16   any

代码块的同步是通过 monitorentermonitorexit 两个指令来实现 synchronized 关键字的。上面的字节码中

0 ~ 5:将 lock 对象入栈,使用 dup 指令复制栈顶元素,并将它存入局部变量表位置 1 的地方,现在栈上还剩下一个 lock 对象

6:以栈顶元素 lock 做为锁,使用 monitorenter 开始同步

7 ~ 8:调用 foo() 方法

11 ~ 12:将 lock 对象入栈,调用 monitorexit 释放锁

16 ~ 20:执行异常处理,字节码会自动加上这段,因为编译器必须保证,无论同步代码块中的代码以何种方式结束(正常 return 或者异常退出),代码中每次调用 monitorenter 必须执行对应的 monitorexit 指令。为了保证这一点,编译器会自动生成一个异常处理器,这个异常处理器的目的就是为了同步代码块抛出异常时能执行 monitorexit。这也是字节码中,只有一个 monitorenter 却有两个 monitorexit 的原因。

总而言之,调用monitorenter指令后,先将lock出栈(解锁)。调用monitoexit指令退出后,再将lock入栈(上锁),如遇到异常则强制monitorexit退出。

二、方法级别的synchronized

方法级别的同步由常量池中方法的 ACC_SYNCHRONIZED 标志来隐式实现。

synchronized public void test() {
}

字节码反编译:

public synchronized void test();
descriptor: ()V
flags: ACC_PUBLIC, ACC_SYNCHRONIZED

JVM 不会使用特殊的字节码来调用同步方法,当 JVM 解析方法的符号引用时,它会判断方法是不是同步的(检查方法 ACC_SYNCHRONIZED 是否被设置)。如果是,执行线程会先尝试获取锁。如果是实例方法,JVM 会尝试获取实例对象的锁,如果是类方法,JVM 会尝试获取类锁。在同步方法完成以后,不管是正常返回还是异常返回,都会释放锁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值