-
AQS提供的几个比较关键的 public 方法有
-
public final void acquire(int arg)
底层用到了 protected boolean tryAcquire(int arg) 和 final boolean acquireQueued(final Node node, int arg) 方法
-
public final void acquireInterruptibly(int arg)
throws InterruptedException底层用到了 private void doAcquireInterruptibly(int arg)
throws InterruptedException 方法 -
public final boolean tryAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException底层用到了 private boolean doAcquireNanos(int arg, long nanosTimeout)
throws InterruptedException 方法 -
public final boolean release(int arg)
底层用到了 protected boolean tryRelease(int arg) 方法
-
public final void acquireShared(int arg)
底层用到了 protected int tryAcquireShared(int arg) 方法
-
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException底层用到了 private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException 方法 -
public final boolean tryAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException底层用到了 protected int tryAcquireShared(int arg) 和 private boolean doAcquireSharedNanos(int arg, long nanosTimeout)
throws InterruptedException 方法 -
public final boolean releaseShared(int arg)
底层用到了 protected boolean tryReleaseShared(int arg) 和 private void doReleaseShared() 方法
这些 public 方法可以按 acquire/release 分,也可以按 shared/不shared 分,而且分为普通版本、可响应interrupt版本、可定时版本(想想ReentrantLock的几种Lock方式底层其实靠的就是这个);
值得注意的是,这些 public 方法用到的很多底层方法是要靠派生类实现(不实现的话可以理解为不支持),例如 tryAcquire 方法
protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); }
-
-
然后看一下 ReentrantLock 和 AQS 相关的部分
-
首先它有一个抽象静态内部类派生了 AQS
abstract static class Sync extends AbstractQueuedSynchronizer { ... }
-
然后 Sync 类又有两个派生类 NonfairSync 和 FairSync 代表公平锁和非公平锁,它们的区别在于 tryAcquire 方法的具体实现
static final class NonfairSync extends Sync { ... protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } } static final class FairSync extends Sync { ... protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } }
-
接下来我们顺着 ReentrantLock 的 lock 方法往里看
-
在构造函数中决定了sync用公平锁还是非公平锁
public void lock() { sync.acquire(1); }
这个函数的说明是这样的
/** * Acquires the lock. * * <p>Acquires the lock if it is not held by another thread and returns * immediately, setting the lock hold count to one. * * <p>If the current thread already holds the lock then the hold * count is incremented by one and the method returns immediately. * * <p>If the lock is held by another thread then the * current thread becomes disabled for thread scheduling * purposes and lies dormant until the lock has been acquired, * at which time the lock hold count is set to one. */
这个说明大概的意思是:如果锁被其他线程占领了会阻塞;否则的话把state这个变量加1
public abstract class AbstractQueuedSynchronizer extend AbstractOwnableSynchronizer implements java.io.Serializable { ... /** * The synchronization state. */ private volatile int state; ... }
-
然后 acquire 是 AQS 的 final 方法,覆盖不了
public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); }
-
然后看 tryAcquire 方法,这个方法被 NonfairSync 和 FairSync 覆盖了,然后 NonfairSync 比较简单,我们就看这个
static final class NonfairSync extends Sync { private static final long serialVersionUID = 7316153563782823691L; protected final boolean tryAcquire(int acquires) { return nonfairTryAcquire(acquires); } }
-
NonfairSync 的 tryAcquire 方法很简单,它调用的是 Sync 类实现的 nonfairTryAcquire 方法(要牢牢记住获取不到是会阻塞的)
abstract static class Sync extends AbstractQueuedSynchronizer { ... final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); // 获取当前线程 int c = getState(); // 获取state变量(不需要阻塞,因为它是volatile修饰的) // state是0,代表没有加锁,所以用cas操作加1,如果成功就返回成功 if (c == 0) { if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); // 设置{@code exclusiveOwnerThread}这个变量为当前线程,这个变量代表exclusive模式下的所有者线程 return true; } } // 如果state不是0,但是所有者线程就是自身的话就让state自增 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); // 直接写state变量就行,因为其他线程肯定写不了 return true; } return false; } ... }
nonfairTryAcquire 这个方法不会阻塞,所以 NonfairSync 的 tryAcquire 方法不会阻塞,它会立刻返回 true(acquire成功)/false(acquire失败)
-
既然 tryAcquire 不会阻塞,那么根据lock方法的语义,说明 acquireQueued 一定会阻塞,acquireQueued 也是 AQS 的 final 方法,它在很多地方都用到了
final boolean acquireQueued(final Node node, int arg) { // interrupted怎么搞的没看懂 boolean interrupted = false; try { // 这是个死循环 for (;;) { final Node p = node.predecessor(); // 当当前结点恰好是头节点的下一个并且tryAcquire成功时,把头节点换成当前结点,并且返回 if (p == head && tryAcquire(arg)) { setHead(node); // 这个也是直接set就行,因为没有竞争 p.next = null; // help GC return interrupted; } if (shouldParkAfterFailedAcquire(p, node)) interrupted |= parkAndCheckInterrupt(); } } catch (Throwable t) { cancelAcquire(node); if (interrupted) selfInterrupt(); throw t; } }
-
这样 lock 方法就看完了,基本思路就是能获取到就立刻返回,不能获取就加上排队队列自旋,for死循环中不断尝试 tryAcquire
-
-
然后看一下 ReentrantLock 的 unlock 方法
public void unlock() { sync.release(1); }
-
release 方法是 AQS 的 final 方法
public final boolean release(int arg) {
if (tryRelease(arg)) { Node h = head; if (h != null && h.waitStatus != 0) unparkSuccessor(h); return true; } return false;
}
-
然后重点是 tryRelease 方法, 这个方法由 Sync 类覆盖
protected final boolean tryRelease(int releases) { int c = getState() - releases; // 判断一下unlock的线程一定是持有锁的线程 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; }
这个比较容易看懂,基本就是让state自减,直到state为0把exclusive线程置为null。所以unlock是不会阻塞的
-
-
-
总结一下就是
-
ReentrantLock 使用的是exclusive模式(非shared),主要覆盖了tryAcquire和tryRelease两个方法(当然也实现了一些其他的)
-
state用于标识锁的状态,0代表没有被抢占,N(N>1)代表被同一个线程上锁了多少次,unlock的时候会一层一层的减1
-
AQS和ReentrantLock
猜你喜欢
转载自blog.csdn.net/captxb/article/details/98971146
今日推荐
周排行