1. acquire() 方法源码分析
public void acquire() throws InterruptedException {
//sync 在Semaphore中默认为非公平锁
sync.acquireSharedInterruptibly(1);
}
public final void acquireSharedInterruptibly(int arg)
throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
//尝试获取锁, 不小于0则,则说明获取到锁,直接返回
//若小于0, 进入doAcquireSharedInterruptibly(), 此方法中会阻塞线程
// tryAcquireShared()为非公平锁实现。NonfairSync
if (tryAcquireShared(arg) < 0)
doAcquireSharedInterruptibly(arg);
NonfairSync 为Semaphore中的内部类
NonfairSync继承自Sync, Sync继承自AbstractQueuedSynchronizer
nonfairTryAcquireShared为Sync中方法
final int nonfairTryAcquireShared(int acquires) {
for (;;) {
int available = getState(); // 当前可用的锁
//当前线程获取锁后,剩余可用的锁
int remaining = available - acquires;
// 如果剩余可用的锁<0, 说明没有足够的锁。返回负数
// 如果剩余可用的锁>=0, 说明获取剩余可用锁成功, 更新剩余可用锁。
if (remaining < 0 ||
compareAndSetState(available, remaining))
return remaining;
}
}
回到acquireSharedInterruptibly()方法,如果剩余锁小于0, 则doAcquireSharedInterruptibly(arg);
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) &&
// 此处阻塞线程, 和countDownLatch的原理是一样的;没解除阻塞一次, 此循环循环一次去尝试获取锁, 因此并不会浪费CPU
parkAndCheckInterrupt())
throw new InterruptedException();
}
} finally {
if (failed)
cancelAcquire(node);
}
}