可重入锁实现细节

Reentrant lock implementation detail

我试图了解 ReentrantLock::lock 方法中的特定细节。我正在查看它并将其视为:

final void lock() {
   if (!initialTryLock()) {
       acquire(1);
   }
}

所以首先它会尝试这种方法:initialTryLock(我会查看 NonfairSync),这样做是这样的:

让我们假设以上失败。然后继续调用 acquire in AbstractQueuedSynchronizer:

public final void acquire(int arg) {
    if (!tryAcquire(arg))
        acquire(null, arg, false, false, false, 0L);
}

它在NonfairSync中首先调用tryAcquire:

protected final boolean tryAcquire(int acquires) {
    if (getState() == 0 && compareAndSetState(0, acquires)) {
        setExclusiveOwnerThread(Thread.currentThread());
        return true;
    }
    return false;
}

你可以看到它试图再次获取锁,尽管initialTryLock已经失败了。理论上,这个 tryAcquire 可以简单地返回 false,对吧?

我认为这是一次潜在的重试,因为在 initialTryLocktryAcquire 的调用之间,锁可能已被释放。这样做的好处可能是因为下一个操作(在 tryAcquire 之后)失败,是该线程的昂贵入队。因此,我想这是有道理的(重试)?

  • initialTryLock() 包含重入功能:

    • Java文档:
      /**
      * Checks for reentrancy and acquires if lock immediately
      * available under fair vs nonfair rules. Locking methods
      * perform initialTryLock check before relaying to
      * corresponding AQS acquire methods.
      */
      abstract boolean initialTryLock();
      
    • NonfairSync 中的源代码:
      final boolean initialTryLock() {
          Thread current = Thread.currentThread();
          if (compareAndSetState(0, 1)) { // first attempt is unguarded
              setExclusiveOwnerThread(current);
              return true;
          } else if (getExclusiveOwnerThread() == current) {
              int c = getState() + 1;
              if (c < 0) // overflow
                  throw new Error("Maximum lock count exceeded");
              setState(c);
              return true;
          } else
              return false;
      }
      
      这里:
      • 第一个 if 检查锁是否被占用(如果空闲则获取锁)
      • 第二个if检查获取的锁是否属于当前线程——这是重入逻辑。
  • tryAcquire() 必须由任何扩展 AbstractQueuedSynchronizer

    的 class 实现
    • 该方法必须执行的操作在 AbstractQueuedSynchronizer
    • 的 javadoc 中进行了描述
      /**
       * Attempts to acquire in exclusive mode. This method should query
       * if the state of the object permits it to be acquired in the
       * exclusive mode, and if so to acquire it.
       * ...
       */
      protected boolean tryAcquire(int arg) {
          throw new UnsupportedOperationException();
      }
    
    • NonfairSync 中的实现正是这样做的(并且不包含重入功能):
    /**
    * Acquire for non-reentrant cases after initialTryLock prescreen
    */
    protected final boolean tryAcquire(int acquires) {
        if (getState() == 0 && compareAndSetState(0, acquires)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }
    

只是添加到

tryAcquire could have simply returned false, right?

没有

这个实现:

boolean tryAcquire(int acquires) {
  return false;
}

会破坏 AbstractQueuedSynchronizer 的工作。

原因是tryAcquire()是在AbstractQueuedSynchronizer中获取锁的唯一方法。

甚至acquire() in the end uses tryAcquire().

所以如果 tryAcquire() 总是返回 false 那么 acquire() 永远不会获得锁。

acquire()用于多个线程争用锁时