'ReentrantLock' 和 'synchronized' 在 CPU 级别上的实现方式有区别吗? 还是他们使用相同的“CAS”方法?
最佳答案
如果我们谈论的是 ReentrantLock
与 synchronized
(也称为“内部锁”),那么最好看看 Lock documentation :
All Lock implementations must enforce the same memory synchronization semantics as provided by the built-in monitor lock:
- A successful lock operation acts like a successful monitorEnter action
- A successful unlock operation acts like a successful monitorExit action
所以一般认为synchronized
只是一种易于使用且简洁的锁定方法。您可以通过使用 ReentrantLock
编写更多代码(但它提供了更多选项和灵 active )来实现完全相同的同步效果。
前段时间 ReentrantLock
在某些条件下(例如高竞争)更快,但现在 Java
使用不同的优化技术(如锁粗化和自适应锁定)来使程序员几乎看不到许多典型场景中的性能差异。
在低争用情况下(例如偏向锁定)优化内在锁也做得很好。 Java 平台的作者非常喜欢synchronized
关键字和内部锁定方法,他们希望程序员不要害怕使用这个方便的工具(并防止可能的错误)。这就是为什么 synchronized
优化和“同步很慢”神话破灭对 Sun 和 Oracle 来说如此重要。
问题的“CPU 部分”:
synchronized
使用内置于 JVM
和 MONITORENTER
/MONITOREXIT
字节码指令中的锁定机制。所以底层实现是特定于 JVM 的(这就是为什么它被称为内在锁)并且 AFAIK 通常(可能会发生变化)使用一个非常保守的策略:一旦锁是“在获取锁时发生线程冲突后“膨胀”,synchronized
开始使用基于操作系统的锁定(“胖锁定”)而不是快速 CAS(“瘦锁定”)并且不再“喜欢”使用 CAS很快(即使争用已经消失)。
ReentrantLock
实现基于AbstractQueuedSynchronizer
,纯Java编码(使用Java 5引入的CAS指令和线程调度),跨平台更稳定,提供更大的灵 active ,并尝试使用快速 CAS 方法每次获取锁(如果失败则使用操作系统级别的锁)。
因此,这些锁实现在性能方面的主要区别在于锁获取策略(在特定的 JVM 实现或情况下可能不存在)。
并且没有一般性的答案哪种锁定更好 + 它可能会随着时间和平台的变化而变化。您应该查看具体问题及其性质,以选择最合适的解决方案(通常在 Java 中)
PS:您很好奇,我强烈建议您查看 HotSpot 源以更深入(并找出特定平台版本的确切实现)。这可能真的有帮助。起点在这里的某个地方:http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/runtime/synchronizer.cpp
关于java - ReentrantLock 与 CPU 级别同步?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36371149/