今日学习内容总结如下:
对于synchronized语句当Java源代码被javac编译成bytecode的时候,会在同步代码块的入口位置和退出位置分别插入monitorenter和monitorexit(2个)字节码指令。而synchronized方法则会被翻译成普通的方法调用和返回指令,在VM字节码层面并没有任何特别的指令来实现被synchronized修饰的方法,而是在Class文件的方法表中将该方法的access_flags字段中的synchronized标志位置1,表示该方法是同步方法并使用调用该方法的对象或该方法所属的Class在JVM的内部对象表示Class做为锁对象
执行monitorenter指令时,线程会为锁对象关联一个ObjectMonitor对象(c++)。线程遇到synchronized同步时,先会进入ObjectMonitor对象的EntryList队列中,然后尝试把ObjectMonitor对象的owner变量设置为当前线程,同时ObjectMonitor对象的monitor中的计数器count加1,即获得对象锁。否则通过尝试自旋一定次数加锁,失败则进入ObjectMonitor对象的cxq队列阻塞等待
synchronized是可重入,非公平锁,因为entryList的线程会先自旋尝试加锁,而不是加入cxq排队等待,不公平
官方文档 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.11.10
同步代码块的同步方法的实现区别
同步语句块使用的是 monitorenter 和 monitorexit 指令,其中 monitorenter 指令指向同步代码块的开始位置,monitorexit 指令指向同步代码块的结束位置方法