关于 synchronized 关键字的疑问
在许多文章中看到 synchronized 会有多种锁的类型,只有到最后才会升级到重量级锁,但是在 JDK1.8 下随便用个 synchronized 就能看到 monitor.enter 和 monitor.exit 字节码指令,这不就矛盾了吗?那么前面的轻量级锁、自旋锁等等去哪儿了?还是说 monitor 不是重量级锁?
在许多文章中看到 synchronized 会有多种锁的类型,只有到最后才会升级到重量级锁,但是在 JDK1.8 下随便用个 synchronized 就能看到 monitor.enter 和 monitor.exit 字节码指令,这不就矛盾了吗?那么前面的轻量级锁、自旋锁等等去哪儿了?还是说 monitor 不是重量级锁?
Java 对象的管程 = 可以用 synchronized 访问的那个同步机制,所谓 synchronized 不过是访问 monitor 的语法机制,而“synchronized 所用的锁会变化”就是说 Java 对象管程里的锁会变化。
首先 synchronized 本来就有隐式监视器实现,免除你手动加锁的那些比如 reenter lock, unlock()。
synchronized 是排他锁,所以字节码可以看到监视器,很正常( java 内部还有哪?就是解释执行字节码啊)绑定到当前对象上,相对的那些可重入锁,自旋锁等轻量锁由于引入了更多功能才不一定会有 monitor 这类监视器。比如我们在 C++ 里面就会利用变量作用域来代替锁,作用域结束,自动解锁(因为对象被收走啦)。
monitor 只是一种实现锁的机制(绑定到”字节码对象”上),可算作排他锁(重量级)锁实现额手段。
“只有到最后才会升级到重量级锁” — 最后?喵喵喵。
歪嘴,我理解主所说 “最后” 是指运行阶段,而不是编译时。坏笑。
Object monitor 是英文词组,意思是对象的管程,这是一个概念。
ObjectMonitor 是 JDK 源代码里类的名字,它是 object monitor 这个概念的是一个实现。
monitorenter 是一个 Java 字节码指令,它的意思是“进入对象的管程”,即它的作用对象是 object monitor 这个概念,至于是调用 ObjectMonitor 的方法还是怎么样,那是实现细节,取决于 object monitor 的状态。
要理解 Java 的同步机制,首先需要理解不特定于 Java 的同步机制。你问的问题似乎是没有搞清楚同步机制(管程)、Java 同步机制( Java 对象的管程、monitorenter )、Java 同步机制的实现( ObjectMonitor 类)之间的关系。
换言之,你所谓的“重量级锁”是 ObjectMonitor,一个 Java 对象的管程可能是用 ObjectMonitor 实现的,也可能是用别的代码实现的,而且同一个对象的管程可以一会儿不用 ObjectMonitor 一会儿用,而 monitorenter 的实际效果是根据对象管程的实现决定的。
我觉得如果真的真的很想搞清楚的话,可以去看看 Hotspot 的源码。
hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/tip/src/share/vm/interpreter/bytecodeInterpreter.cpp#l1816