共计 1419 个字符,预计需要花费 4 分钟才能阅读完成。
1.idea 查看字节码 jclasslib 插件装置
2. 从字节码角度剖析 synchronized 实现
3. 总结
1.idea 查看字节码 jclasslib 插件装置
synchronize 这个关键字咱们必定曾经不生疏了,接下来咱们从字节码这个角度来进行分析一下,它为什么会有加锁的成果。咱们先装置一下 jclasslib 插件,不便咱们查看 java 的字节码。
点击 view –> show Bytecode With Jclasslib
就能够看到这个文件的字节码啦。
2. 从字节码角度剖析 synchronized 实现
2.1synchronized 同步代码块
public class LockByteDemo {final Object object = new Object();
public void m1() {synchronized (object) {System.out.println("-------------hello sync");
//throw new RuntimeException("6");
}
}
}
咱们对 m1() 这个 ssynchronized 同步代码块办法进行查看一下字节码。
咱们发现,它应用的是 monitorenter 指令 和 monitorexit 指令。
monitor:
其实每一个对象都有一个 monitor,就是监视器,当线程获取 monitor 胜利的时候,这个对象就被锁住了。
monitorenter 指令:
线程执行 monitorenter 就是为了尝试获取 monitor 的拥有权,过程为:
1)如果一个 monitor 的数值是 0,那么线程间接进入 monitor,并且将 monitor 置为 1,并将对象的抢占该线程置为该线程。
2)如果该线程曾经占用 monitor,则间接进入,monitor 数 +1(可重入锁)
3)如果该对象的抢占线程不是该线程,那么该线程就会被阻塞,直到 monitor 的数值变成 0,再次抢占。
monitorexit 指令:
执行 monitorexit 的线程必须是曾经领有该对象 monitor 的线程,执行 monitorexit 命令后,monitor 的进入数会减 1,当减为 0 时,其它线程就能够尝试取得 monitor 的所有权。
然而这里有一个疑难,为什么只有一个 monitorenter,然而有两个 monitorexit?
咱们能够思考一下,这其实是和 try/finally 是一个情理,咱们个别编程的时候,都要在 finally 里加一个解锁 unlock,避免异常情况的产生,那么这里也是一样的,为了避免代码出现异常,最初在进行 monitorexit 一下。
2.2synchronized 一般同步办法
咱们会发现,一般办法标记位多了一个 ACC_SYNCHRONIZED 拜访标记。
当咱们调用一个办法的时候,会先查看办法的 ACC_SYNCHRONIZED 拜访标记是否被设置,如果设置了,线程执行会先尝试获取 monitor,最初在办法实现的时候开释 monitor。
2.3synchronized 动态同步办法
动态同步办法的原理也是一样的,不过再多一个 ACC_STATIC 标记位,用来辨别是否动态同步办法。
3. 总结
明天咱们分析了 synchronized 的字节码角度实现,其实多减少这种内功的修炼,会让我写代码的时候,有一种不一样的感觉,以前写 synchronized 的时候,脑子里只有单单一个 synchronized 关键字,当初又会联想到字节码,可能就是今人说的,从看山是山,到看山不是山的转变。