在前面的文章中,我们分别介绍了 Reentrantlock、Semaphore、CountDownLatch 等 JUC 包中的提供的锁及工具类。
它们的底层实现都是通过一个内部类 Sync 直接继承 AQS,然后自己实现 tryAcquire() 和 tryRelease() 方法。
1.Reentrantlock
Reentrantlock 提供了公平锁(FairSync)和非公平锁(NonFairSync)两种实现,我们最常用的就是非公平锁的实现(默认)
注:公平锁和非公平锁是针对加锁而言的,在释放锁没有区别
final boolean nonfairTryAcquire(int acquires) {
// 获取当前线程
final Thread current = Thread.currentThread();
// 获取 AQS 的 state
int c = getState();
// 如果 state=0,则当前线程有机会直接获得锁
if (c == 0) {
// 通过 CAS 去修改 state,如果修改成功,则表示当前线程拿锁成功
if (compareAndSetState(0, acquires)) {
// 将拿锁线程置为当前线程
setExclusiveOwnerThread(current);
return true;
}
}
// 如果已经有线程拿锁了,并且是当前线程,则表示重入
else if (current == getExclusiveOwnerThread()) {
// 将 state+要申请的资源数
int nextc = c + acquires;
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
// 重置 state
setState(nextc);
return true;
}
// 否则,拿锁失败
return false;
}
再来看看 tryRelease()
protected final boolean tryRelease(int releases) {
// 获取 AQS 的 state,并计算 c=state-释放资源数
int c = getState() - releases;
// 判断当前线程是否是拿锁线程
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
// c=0,表示能够将所有资源释放
if (c == 0) {
free = true;
// 将AQS保存的拿锁线程置为null
setExclusiveOwnerThread(null);
}
// 重置state
setState(c);
return free;
}
2.Semaphore
Semaphore 是一个并发工具类,可以用来做限流的场景,即同一时刻,只允许指定的数量的线程去运行。
final int nonfairTryAcquireShared(int acquires) {
// 自旋,保证对 state 的修改一定能成功
for (;;) {
// 获取当前 AQS 的 state
int available = getState();
// 计算修改后的 state
int remaining = available - acquires;
// 如果修改后 state<0,则拿锁失败
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
这里一定要注意,Semaphore 复用 AQS 时,在内部类 Sync 通过构造器重置了 state 为我们设置的限流值,
这也是 Semaphore 同时能运行指定数量线程的关键所在。再注意一点,虽然 Semaphore 采用的是共享锁模式,但是就算所有线程都被唤醒,也只有前permits个线程能拿到锁运行,其它线程还得去休眠。
再来看 tryReleaseShared()
protected final boolean tryReleaseShared(int releases) {
// 自旋,保证 state 的 CAS 一定能成功
for (;;) {
// 获取当前 AQS 的 state
int current = getState();
// 获取释放锁后的 state
int next = current + releases;
if (next < current) // overflow
throw new Error("Maximum permit count exceeded");
// CAS 修改state
if (compareAndSetState(current, next))
return true;
}
}
CountDownLatch
CountDownLatch 是一个门栓,可用于线程间通信。
protected int tryAcquireShared(int acquires) {
// state=0 则能获得锁
return (getState() == 0) ? 1 : -1;
}
跟 Semaphore 一样,CountDownLatch 也是在 Sync 的构造器中手动设置了 state

再加上 CountDownLatch 采用的是共享锁模式,所以当 state 减为0时,所以线程都会醒来;醒来之后再 tryAcquireShared() 也都能获得锁。
再来看 tryReleaseShared()
protected boolean tryReleaseShared(int releases) {
// Decrement count; signal when transition to zero
for (;;) {
// 拿到 AQS 的 state
int c = getState();
// 如果 state 已经为0了,释放锁失败
if (c == 0)
return false;
// 否则,state-1
int nextc = c-1;
// CAS 更新 state
if (compareAndSetState(c, nextc))
return nextc == 0;
}
}







还没有评论,来说两句吧...