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()这个synchronized同步代码块方法进行查看一下字节码。
我们发现,它使用的是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关键字,现在又会联想到字节码,可能就是古人说的,从看山是山,到看山不是山的转变。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。