关于 synchronized 关键字的疑问

2020-10-12 22:38:39 +08:00
 MeloForsaken

在许多文章中看到 synchronized 会有多种锁的类型,只有到最后才会升级到重量级锁,但是在 JDK1.8 下随便用个 synchronized 就能看到 monitor.enter 和 monitor.exit 字节码指令,这不就矛盾了吗?那么前面的轻量级锁、自旋锁等等去哪儿了?还是说 monitor 不是重量级锁?

1793 次点击
所在节点    程序员
8 条回复
ZSeptember
2020-10-12 22:58:46 +08:00
这种锁不是字节码级别的,是 JVM 内部实现,没有暴露给字节码。
其实,偏向锁用处不是那么的大,现在已经有 JEP 去删除偏向锁了。
user8341
2020-10-12 23:15:20 +08:00
许多文章?什么文章啊?
geelaw
2020-10-12 23:30:04 +08:00
楼主看的文章里说 synchronized 锁有多种状态且会变化,然后又问 monitor (管程)锁是什么,显然是没有理解 synchronized 的原理、Java 对象结构、什么是 Java 对象的管程。

Java 对象的管程 = 可以用 synchronized 访问的那个同步机制,所谓 synchronized 不过是访问 monitor 的语法机制,而“synchronized 所用的锁会变化”就是说 Java 对象管程里的锁会变化。
yanyueio
2020-10-12 23:30:28 +08:00
#1 正解,但谈底层的时候,一定要注明是哪个 jdk 版本,什么版本的 jdk,最好看一下其提交 commit id,甚至是什么虚拟机执行的,编译是什么 javac 工具。(普通最好)


首先 synchronized 本来就有隐式监视器实现,免除你手动加锁的那些比如 reenter lock, unlock()。
synchronized 是排他锁,所以字节码可以看到监视器,很正常( java 内部还有哪?就是解释执行字节码啊)绑定到当前对象上,相对的那些可重入锁,自旋锁等轻量锁由于引入了更多功能才不一定会有 monitor 这类监视器。比如我们在 C++ 里面就会利用变量作用域来代替锁,作用域结束,自动解锁(因为对象被收走啦)。

monitor 只是一种实现锁的机制(绑定到"字节码对象"上),可算作排他锁(重量级)锁实现额手段。

“只有到最后才会升级到重量级锁” --- 最后?喵喵喵。

歪嘴,我理解楼主所说 "最后" 是指运行阶段,而不是编译时。坏笑。
MeloForsaken
2020-10-13 09:37:40 +08:00
@ZSeptember @geelaw @user8341 @yanyueio
"事实上,只有在 JDK1.6 之前,synchronized 的实现才会直接调用 ObjectMonitor 的 enter 和 exit,这种锁被称之为重量级锁。"
这句话是不是有点问题,如果说重量级锁才会有 enter 和 exit 字节码指令的话,那为什么 JDK1.8 下随便写个 synchronized 代码块的 demo 反编译后的字节码指令里面会有 enter 和 exit,这不表示 synchronized 默认使用重量级锁?还是说偏向锁、轻量级锁也会涉及到 enter 和 exit 指令?
谢谢!!!
geelaw
2020-10-13 10:18:27 +08:00
@MeloForsaken #5 请你 cite 内容的时候给出链接。
另外你似乎没有搞懂 object monitor 和 ObjectMonitor 和 monitorenter 的关系。

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 的实际效果是根据对象管程的实现决定的。
MeloForsaken
2020-10-13 10:43:43 +08:00
@geelaw 理解了,感谢
user8341
2020-10-13 11:15:02 +08:00
@MeloForsaken

我觉得如果真的真的很想搞清楚的话,可以去看看 Hotspot 的源码。

hg.openjdk.java.net/jdk8u/jdk8u/hotspot/file/tip/src/share/vm/interpreter/bytecodeInterpreter.cpp#l1816

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/714319

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX