Java 飞行记录器中的 ReentrantLock

ReentrantLock in Java Flight Recorder

ReentrantLock使用什么样的机制?我试图了解它会出现在 Java 飞行记录下的什么位置。我的期望是锁定将在 Java Monitor Wait 部分下,但事实并非如此。

背景:
我正在尝试通过捕获 java 飞行记录来调试有问题的 ReentrantLock。锁本身很简单:

public class SomeClass {
  private final ReentrantLock lock = new ReentrantLock();
  
  public void capture() {
    boolean exclusive = someFunction();
    try {
      if (exclusive) {
        lock.lock();
      }  

      // critical code 

    } finally {
      if (exclusive) {
        lock.unlock();  
      }
    }
  }
}

在我的实验中,我的应用程序应该调用 capture 函数 200 万次,在某些情况下,锁会根据 someFunction() 被激活。由于我没有得到预期的结果,我将函数硬编码为始终为真,但在我的记录中没有观察到 200 万个 Java 监视器等待事件。

Zulu Mission Control screenshot

ReentrantLocks 不使用 Java 内在监视器。通过synchronized关键字同步和Locks是不同的概念。另请参阅 相关答案。

通过 synchronized 实现的同步(= 使用内部监控器/锁)将锁信息直接存储在对象的内部内存表示中,并以本机代码实现。锁将锁信息存储在自己的 Java 对象中,并在 Java 代码中实现。有了它,锁比内置的固有监视器更灵活。例如,它们允许在对象边界上互斥,它们可以授予多个线程并发读取访问权限,并让开发人员在公平或不公平锁定之间进行选择。内置同步无法实现的所有事情。

因此,虽然 ReentrantLock(如 JavaDoc 中所述)与使用 synchronized 方法和语句访问的隐式监视器锁具有相同的基本行为和语义,但它是在一个完全不同的方式。

灵活性的获得是以复杂性为代价的。虽然跟踪内部监视器的状态非常简单,但监视和检测甚至分析 ReentrantLocks 的死锁要困难得多。据我所知,与内置的内部锁/监视器相比,大多数监视工具(包括飞行记录器)不提供或仅提供有限的锁支持。

您将开始欣赏内置同步机制的简单性,这是您第一次分析大量使用 ReentrantLocks 或其他 Lock 实现的生产代码中的死锁;-)

有为 java.util.concurrent 添加事件的增强请求,但在不增加开销的情况下很难做到。

https://bugs.openjdk.java.net/browse/JDK-8067779