返回

AQS 深度解析:共享锁揭秘

后端

AQS 共享锁的奥秘

获取共享锁的过程与独占锁的过程在整体上非常相似,但其中也有一些关键的区别。在 acquireShared 方法中,AQS 会首先检查当前线程是否已经持有共享锁。如果已经持有,则直接增加共享锁计数器并返回。如果当前线程没有持有共享锁,则会尝试获取独占锁。如果能够成功获取独占锁,则会将其转换为共享锁并返回。如果获取独占锁失败,则会将当前线程加入到等待队列中,并阻塞等待其他线程释放共享锁。

public final void acquireShared(int arg) {
    if (tryAcquireShared(arg) < 0)
        doAcquireShared(arg);
}

public final int tryAcquireShared(int acquires) {
    Thread current = Thread.currentThread();
    if (exclusiveOwnerThread == current) {
        int available = sharedCount;
        if (available >= acquires) {
            sharedCount = available - acquires;
            return acquires;
        }
    }
    return -1;
}

public final void doAcquireShared(int acquires) {
    final Node node = addWaiter(Node.SHARED);
    boolean failed = true;
    try {
        boolean interrupted = false;
        for (;;) {
            final Node p = node.predecessor();
            if (p == head && tryAcquireShared(acquires) < 0) {
                interrupted = Node.awaitLock(node, interrupted);
            } else {
                if (shouldParkAfterFailedAcquire(p, node))
                    interrupted = Node.parkAndCheckInterrupt();
                failed = false;
                return;
            }
        }
    } finally {
        if (failed)
            cancelAcquire(node);
    }
}

共享锁与独占锁的异同

通过对 AQS 共享锁获取过程的分析,我们可以发现它与独占锁的获取过程在整体上非常相似。它们都涉及到尝试获取锁、加入等待队列、阻塞等待等步骤。但是,它们之间也存在一些关键的区别。

  • 共享锁可以同时被多个线程持有,而独占锁只能被一个线程持有。
  • 获取共享锁时,如果当前线程已经持有共享锁,则直接增加共享锁计数器并返回。
  • 获取独占锁时,如果当前线程已经持有共享锁,则需要先释放共享锁,然后再尝试获取独占锁。

总结

在本文中,我们深入分析了 AQS 共享锁的获取过程,并将其与独占锁的获取过程进行了比较。通过这种方式,我们对 AQS 的并发控制机制有了更加全面的理解。在实际的开发中,我们可以根据需要选择使用共享锁或独占锁来保护我们的共享资源,从而提高程序的并发性和安全性。