代码之家  ›  专栏  ›  技术社区  ›  Eugene

可重入锁实现细节

  •  2
  • Eugene  · 技术社区  · 4 年前

    我正试图了解其中的一个具体细节 ReentrantLock::lock 方法我将其视为:

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

    因此,首先它尝试这种方法: initialTryLock (我进去看看 NonfairSync

    • 它有一个 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 先进的 非空中同步 :

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

    您可以看到它试图获取锁 ,虽然 初始锁定 已经失败了。理论上,这 tryAcquire 错误的

    我认为这是一种潜在的重试,因为 初始锁定 ,锁可能已被释放。这样做的好处可能是因为下一次操作(在 tryAcquire )失败,是此线程的昂贵队列。因此,我想这是有意义的(重试),因为这?

    0 回复  |  直到 4 年前
        1
  •  2
  •   user15114747    4 年前

    只是为了增加 the answer above .

    tryAcquire

    boolean tryAcquire(int acquires) {
      return false;
    }
    

    将破坏 AbstractQueuedSynchronizer

    原因是 tryAcquire() 只有这样才能打开锁 抽象队列同步器 .

    即使 acquire() in the end uses tryAcquire() .

    所以如果 tryAcquire() 总是回来 false 然后 获得 他永远不会得到锁。

    当多个线程争用锁时使用。

        2
  •  1
  •   rte    4 年前
    • 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
        • 第二 如果 检查获取的锁是否属于当前线程这是重入逻辑。
    • tryAcquire() 必须由任何扩展类实现 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();
        }
      
      • 实施 确实如此(不包含可重入功能):
      /**
      * 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;
      }