在前面的文章中,有详细地介绍java字节码相关的知识,有兴趣的可以提前了解一下。
10.Java字节码角度分析:异常_finally——提升硬实力10
从字节码角度分析:Synchronized
我们知道 synchronized 是同步代码块、方法,即通过加锁、解锁来实现的,但我们会显示地加锁,并没有显示地解锁,jvm是如何保证 synchronized 锁能在任何情况下得到正确地释放呢?或者说成对出现呢?带着问题,通过示例代码及对应的字节码一控究竟。
- // 从字节码角度分析:synchronized
- public class T20_ByteAnalyseSynchronized {
- public static void main(String[] args) {
- Object lock = new Object();
- synchronized (lock) {
- System.out.println("ok");
- }
- }
- }
上述代码通过:javap -v T20_ByteAnalyseSynchronized.class进行反编译,得到如下字节码。
- public static void main(java.lang.String[]);
- descriptor: ([Ljava/lang/String;)V
- flags: ACC_PUBLIC, ACC_STATIC
- Code:
- stack=2, locals=4, args_size=1
- 0: new #2 // new Object
- 3: dup
- 4: invokespecial #1 // invokespecial
:()V - 7: astore_1 // lock引用 -> lock
- 8: aload_1 // <- lock (synchronized 开始)
- 9: dup
- 10: astore_2 // lock引用 -> slot 2
- 11: monitorenter // monitorenter (lock引用)
- 12: getstatic #3 // <- System.out
- 15: ldc #4 // <- "ok"
- 17: invokevirtual #5 // invokevirtual println:(Ljava/lang/String;)V
- 20: aload_2 // <- slot 2 (lock引用)
- 21: monitorexit // monitorexit (lock引用)
- 22: goto 30
- 25: astore_3 // any -> slot 3
- 26: aload_2 // <- slot 2 (lock引用)
- 27: monitorexit // monitorexit (lock引用)
- 28: aload_3
- 29: athrow
- 30: return
- Exception table:
- from to target type
- 12 22 25 any
- 25 28 25 any
- LineNumberTable: ...
- LocalVariableTable:
- Start Length Slot Name Signature
- 0 31 0 args [Ljava/lang/String;
- 8 23 1 lock Ljava/lang/Object;
- StackMapTable: ...
为了更好地理解 synchronized 加锁和释放锁的整个流程,需要将正常流程和异常流程进行确认。
注意:
- 方法级别的 synchronized 不会在字节码指令中有所体现
总结:
- synchronized 是通过
monitorenter
和monitorexit
实现锁的获取和释放,并且他俩是成对出现。 monitorenter 入口只有一个,但是 monitorexit 的出口有多个,因为程序异常也需要将锁释放 - 当代码段执行结束或出现异常后会自动释放对监视器的锁定。
文章最后,给大家推荐一些受欢迎的技术博客链接:
- Hadoop相关技术博客链接
- Spark 核心技术链接
- JAVA相关的深度技术博客链接
- 超全干货--Flink思维导图,花了3周左右编写、校对
- 深入JAVA 的JVM核心原理解决线上各种故障【附案例】
- 请谈谈你对volatile的理解?--最近小李子与面试官的一场“硬核较量”
- 聊聊RPC通信,经常被问到的一道面试题。源码+笔记,包懂
欢迎扫描下方的二维码或 搜索 公众号“10点进修”,我们会有更多、且及时的资料推送给您,欢迎多多交流!
评论记录:
回复评论: