2

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

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

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

  • 它做了 a compareAndSwap(0, 1),这意味着如果没有人持有锁(0)并且我可以抓住它(1),我现在持有锁。
  • 如果上述失败,它会检查请求锁的线程是否已经是所有者。
  • 如果失败,它会返回false,这意味着我无法获得锁。

让我们假设上述失败。然后它继续并acquire调用AbstractQueuedSynchronizer

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

tryAcquire它首先调用NonfairSync

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

您可以看到它再次尝试获取锁,尽管initialTryLock已经失败。从理论上讲,这本tryAcquire可以简单地返回false,对吗?

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

4

2 回答 2

2

只是为了补充上面的答案

tryAcquire可以简单地返回false,对吗?

不。

这个实现:

boolean tryAcquire(int acquires) {
  return false;
}

会破坏AbstractQueuedSynchronizer.

原因是tryAcquire()只有这样才能取到锁AbstractQueuedSynchronizer

甚至acquire()最终用途tryAcquire()

因此,如果tryAcquire()总是返回false,则acquire()永远不会获得锁。

并且acquire()在多个线程争夺锁时使用。

于 2021-01-31T01:26:42.950 回答
1
  • initialTryLock()包含重入功能:

    • 文档:
      /**
      * 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

    • 该方法必须做什么在其 javadoc 中描述AbstractQueuedSynchronizer
      /**
       * 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;
    }
    
于 2021-01-30T04:14:13.647 回答