java同步标记_Java精通并发-同步方法访问标志与synchronized关键字之间的关系

继续基于上一次https://www.cnblogs.com/webor2006/p/11428811.html来研究synchronized关键字在字节码中的表现,在上一次文末提出了一个这样的问题:

f59703aea2eabb0aa876e06017c26f17.png

其对应的源代码如下:

3db9208a1d2ef3db579d8228a78d1332.png

这是因为上面这个同步块中的代码会有抛异常的情况发生,虽说我们肉眼看着好像只有一条打印语句,但是JVM需要考虑同步块抛异常的情况其锁也要正常被释放,所以我们可以看到有异常抛出相关的助记符:

6a94a7dd4c83eb707b39687a76c5acda.png

所以可以总结一下:“当我们使用synchronized关键字来修饰代码块时,字节码层面上是通过monitorenter和monitorexit指令来实现的锁的获取和释放动作。”

好,接着来改一下程序:

6df94685aa0ba00de219cf3854998cc3.png

然后再字节码反编译:

315feaa94adc613ba7bcf3a0346a5c41.png

这又如何解释呢?因为该方法无论如何肯定都是以异常进行同步块退出的,这是唯一的可能,没有其它更多的路径,所以这就是为啥只有一个monitorexit助字符存在的原因。

所以又可以总结为:“当线程进入到monitorenter指令后,线程将会持有Monitor对象,退出monitorexit指令后,线程将会释放Monitor对象。”

下面再来改造代码,来让synchronized修饰方法,而非同步块,如下:

3177d9cee8bcffb01f639c8cfffde999.png

8ca39a1c5070a9ec73197564d930b8c9.png

那。。对于修饰方法的同步块在字节码中是如何来体现该方法是一个同步方法呢?实际上是通过方向的flag来体现的,如下:

2187b7e23c9bba9886b34ed3fd1de9b0.png

所以,又总结如下:“对于synchronized关键字修饰方法来说,并没有出现monitorenter和monitorexit指令,而是出现了一个ACC_SYNCHRONIZED标志。原因是JVM使用了ACC_SYNCHRONIZED访问标志来区分一个方法是否为同步方法;当方法被调用时,调用指令会检查该方法是否拥有ACC_SYNCHRONIZEDS标志,如果有,那么执行线程将会先持有方法所在对象的Monitor对象,然后再去执行方法体;在该方法执行期间,其他任何线程均无法再获取到这个Monitor对象,当线程执行完该方法后,它会释放掉这个Monitor对象。”

继续再改造:

756238c463aa4bf4599303e6910eb306.png

好,再来看一下此时字节码的情况:

b223b92ac5cd74ddbe6b9fe46896fb12.png

然后此时同步的情况也是体现在flags中的,如下:

5a2eee92529906348987da207ecde85c.png

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值