这里的描述,其实都基于上一个AQS的分析,AQS不熟悉可以看下之前写的,有大致介绍AQS描述
先看ReentrantLock数据结构
构造方法:
// 默认构建一个非公平的锁
public ReentrantLock() {
sync = new NonfairSync();
}
// 根据Boolean 决定构建公平和非公平
public ReentrantLock(boolean fair) {
sync = fair ? new FairSync() : new NonfairSync();
}
public void lock() {
sync.lock();
}
public void unlock() {
sync.release(1);
}
// lock和unlock的逻辑,都是取决于不同的sync实现
// ************** NonfairSync **************
final void lock() {
// CAS 设置state,成功直接获取到锁
if (compareAndSetState(0, 1))
setExclusiveOwnerThread(Thread.currentThread());
else
// CAS失败,调用父类AQS方法,尝试获取锁
acquire(1);
}
AQS:
public final void acquire(int arg) {
if (!tryAcquire(arg) &&
// 构建node节点,加入CLH队列
acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
selfInterrupt();
}
NonFailSync: tryAcquire调用到下面方法
final boolean nonfairTryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
if (compareAndSetState(0, acquires)) {
setExclusiveOwnerThread(current);
return true;
}
}
else if (current == getExclusiveOwnerThread()) {
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
// 总结: lock 会先CAS拿锁,拿不到的话,AQS再次尝试拿锁。拿到返回,否则队列阻塞线程,等待释放被唤醒
// ********************* unlock **************************
sync.release(1);
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
// state=0 && head节点就,唤醒h.next 线程
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease: 扣减state state=0时返回true
protected final boolean tryRelease(int releases) {
int c = getState() - releases;
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
公平锁差不多,就只标记下不一样的地方吧
// 因为是公平锁,不能直接CAS设置,因为需要从队列取head
final void lock() {
acquire(1);
}
protected final boolean tryAcquire(int acquires) {
final Thread current = Thread.currentThread();
int c = getState();
if (c == 0) {
// 重点再state=0时,需要多判断是否是head节点
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;
}
}
// 当h==t || (h.next!=null && s.thread== currentThread)
// 意思就是,当前节点是头节点的next时,CAS拿锁
public final boolean hasQueuedPredecessors() {
// The correctness of this depends on head being initialized
// before tail and on head.next being accurate if the current
// thread is first in queue.
Node t = tail; // Read fields in reverse initialization order
Node h = head;
Node s;
return h != t &&
((s = h.next) == null || s.thread != Thread.currentThread());
}
先整理一下countDownLatch的数据结构
和ReenTrantLock一样,内部持有一个Sync引用,实现AQS模板方法的try*** 来定制化操作
按方法挨个看下去:
构造方法:
public CountDownLatch(int count) {
if (count < 0) throw new IllegalArgumentException("count < 0");
this.sync = new Sync(count);
}
// 内部类 Sync
private static final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 4982264981922014374L;
// 构造方法传递的count数,透传给AQS的state
Sync(int count) {
setState(count);
}
int getCount() {
return getState();
}
// state=0时,返回1
protected int tryAcquireShared(int acquires) {
return (getState() == 0) ? 1 : -1;
}
// 释放锁 state=0 false 否则 扣减释放
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
}
// ********** 阻塞流程 *****************
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
//AQS 响应中断 tryAcquireShared ,当state>0时,会走进doAcquireShardInteruptibly
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
}
// AQS 当是head的时候,并且state=0时,才能拿锁,首节点拿到锁,往下继续唤醒CLH链上的其他系节点信息,被唤醒,否则阻塞
private void doAcquireSharedInterruptibly(int arg)
throws InterruptedException {
final Node node = addWaiter(Node.SHARED);
boolean failed = true;
try {
for (;;) {
final Node p = node.predecessor();
if (p == head) {
int r = tryAcquireShared(arg);
if (r >= 0) {
setHeadAndPropagate(node, r);
p.next = null; // help GC
failed = false;
return;
}
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}
// state阻塞在这里,state初始化就是多个,线程await最终会park在这里,等待唤醒
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
return Thread.interrupted();
}
// ********** 阻塞流程 *****************
// ********** 释放流程 *****************
public void countDown() {
sync.releaseShared(1);
}
public final boolean releaseShared(int arg) {
if (tryReleaseShared(arg)) {
doReleaseShared();
return true;
}
return false;
}
// state=0 直接return false 否则doReleaseShared
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
int c = getState();
if (c == 0)
return false;
int nextc = c-1;
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}
// 将队列中的移出 head节点就唤醒,
private void doReleaseShared() {
for (;;) {
Node h = head;
if (h != null && h != tail) {
int ws = h.waitStatus;
if (ws == Node.SIGNAL) {
if (!compareAndSetWaitStatus(h, Node.SIGNAL, 0))
continue; // loop to recheck cases
// 唤醒
unparkSuccessor(h);
}
else if (ws == 0 &&
!compareAndSetWaitStatus(h, 0, Node.PROPAGATE))
continue; // loop on failed CAS
}
if (h == head) // loop if head changed
break;
}
}
// ********** 释放流程 *****************
总结:初始化一个countDownLatch,携带的int参数,本质是设置到AQS的state里,用来阻塞线程
await() 内部实际是acquire,判断state>0时,添加Node节点,并且阻塞线程
countDown() 内部是release, state>0 时,做state--操作,并setState,当state==0时,触发doReleaseShared()方法, 唤醒之前LockSuport.park的线程,按照CLH阻塞顺序,依次唤醒。