8

当我们synchronized在java中使用关键字时,究竟使用了哪个同步原语?Lock, Semaphore, Monitor, Mutex?

编辑: JVM 如何在本机级别实现锁定?

4

2 回答 2

10

在字节码级别,java hasmonitorentermonitorexit操作,记录在Java 虚拟机规范的这个页面中,下面粘贴了片段(objectref是操作的操作数,取自堆栈):

监视器输入片段

每个对象都有一个与之关联的监视器。执行 monitorenter的线程获得与objectref关联的监视器的所有权。如果另一个线程已经拥有与objectref关联的监视器,则当前线程等待直到对象被解锁,然后再次尝试获得所有权。如果当前线程已经拥有与objectref关联的监视器,它会增加监视器中的计数器,指示该线程进入监视器的次数。如果与objectref关联的监视器不属于任何线程,则当前线程将成为监视器的所有者,将此监视器的条目计数设置为 1。

监视器退出片段

当前线程应该是与objectref引用的实例关联的监视器的所有者。线程递减指示它进入此监视器的次数的计数器。如果结果计数器的值变为零,则当前线程释放监视器。如果与objectref关联的监视器 空闲,则允许等待获取该监视器的其他线程尝试这样做。

因此,“监视器”是答案,NPE 的答案中引用的这个和 JLS 都没有指定在本机代码级别发生的情况。如果您有特定的平台(CPU 和操作系统)和特定的 JVM 实现(包括版本),您当然可以查看 JVM 源代码(如果它是开源 JVM),或者在这里询问。

从 1997 年开始,我也偶然发现了这个博客,其中有更多细节。

于 2013-03-28T14:45:54.430 回答
7

来自 JLS(第 17.1 节。同步):

Java 编程语言为线程之间的通信提供了多种机制。这些方法中最基本的是同步,它是使用监视器实现的。Java 中的每个对象都与一个监视器相关联,线程可以锁定或解锁监视器。一次只有一个线程可以锁定监视器。任何其他试图锁定该监视器的线程都会被阻塞,直到它们能够获得对该监视器的锁定。一个线程 t 可能会多次锁定一个特定的监视器;每次解锁都会反转一次锁定操作的效果。

因此,“监视器”是您第一个问题的答案。

至于第二个问题,这是一个未指定的实现细节。

于 2013-03-28T14:37:07.877 回答