Lock方法
tryAcquire 表示尝试加锁的方法
abstract static class Sync extends AbstractQueuedSynchronizer {
protected final boolean tryAcquire(int acquires) {
Thread current = Thread.currentThread();
int c = getState();
//
int w = exclusiveCount(c);
// c != 0 说明有线程占用锁
if (c != 0) {
// c != 0 && w==0的时候表示占用线程超过最大值65535
// c != 0 && 当前线程不是重入线程
if (w == 0 || current != getExclusiveOwnerThread())
return false;
// 再次判断是否超过最大值
if (w + exclusiveCount(acquires) > MAX_COUNT)
throw new Error("Maximum lock count exceeded");
// 疑问:为什么不用CAS,如果这里多个线程执行怎么办?(不存在的)
// current != getExclusiveOwnerThread() 已经保证了是同一个线程。
setState(c + acquires);
return true;
}
// writerShouldBlock() 判断是否阻塞 返回false,才能执行CAS操作尝试占用锁
// writerShouldBlock() 方法为模板方法FairSync和NonfairSync都有实现
// NonfairSync 中 直接返回false, 体现出非公平性。
// FairSync 中 hasQueuedPredecessors()
// 如果当前线程在队列的头部或队列为空(tail != head), return false, 进行下面CAS获取锁操作
// 如果头结点后面的排队节点是当前线程((s = head.next) == null || s.thread != Thread.currentThread()), return false,进行下面CAS获取锁操作
if (writerShouldBlock() ||
!compareAndSetState(c, c + acquires))
return false;
setExclusiveOwnerThread(current);
return true;
}
}
tryAcquire失败后, 加入到AQS队列
private Node addWaiter(Node mode) {
// mode EXCLUSIVE 独占锁 SHARED 共享锁
Node node = new Node(Thread.currentThread(), mode);
// Try the fast path of enq; backup to full enq on failure
Node pred = tail;
if (pred != null) {
// 初始化队列成功后 尾节点不为null
node.prev = pred;
// CAS node节点变成尾节点
// 可能会CAS设置失败,可能会出现下面 图1 这种情况,后面enq方法会循环CAS入队
if (compareAndSetTail(pred, node)) {
pred.next = node;
return node;
}
}
enq(node);
return node;
}
private Node enq(final Node node) {
for (;;) {
Node t = tail;
if (t == null) { // Must initialize
// 队列初始化,CAS头指针指向Node节点
if (compareAndSetHead(new Node()))
tail = head;
} else {
// CAS尾插
node.prev = t;
if (compareAndSetTail(t, node)) {
t.next = node;
return t;
}
}
}
}
图1
进入队列后,acquireQueued
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
// 返回前一个节点
// 疑问:为什么用final修饰?
final Node p = node.predecessor();
// 如果前面就是头节点,也就是有可能前面的节点很快就解锁了,可再次尝试CAS
if (p == head && tryAcquire(arg)) {
// 如果是公平锁,并且执行到writerShouldBlock(),头节点后面没有线程排队,并且CAS获取锁成功了,设置当前线程为队列头节点。
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
// shouldParkAfterFailedAcquire返回true后,parkAndCheckInterrupt就会进行LockSupport.park()操作对线程真正的阻塞。
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
shouldParkAfterFailedAcquire方法解析
/** 指示线程已取消 */
static final int CANCELLED = 1;
/** 表示后继线程需要取消停放 */
static final int SIGNAL = -1;
/** 表示线程正在等待条件 */
static final int CONDITION = -2;
/** 指示下一个 acquireShared 应该无条件传播 */
static final int PROPAGATE = -3;
private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
// pred 指向node的前驱节点(node.predecessor())
// waitStatus默认为0
int ws = pred.waitStatus;
if (ws == Node.SIGNAL)
// Node.SIGNAL表示后继线程需要取消停放(第一次进来的时候设置的)
// 返回true后,就会对当前线程进行阻塞LockSupport.park()。
return true;
if (ws > 0) {
// CANCELLED状态(线程已取消)才能进来
do {
node.prev = pred = pred.prev;
} while (pred.waitStatus > 0);
pred.next = node;
} else {
// 第一次会进来这里,设置当前node节点的前驱节点waitStatus=Node.SIGNAL(-1)
compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
}
return false;
}
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this);
// 为什么有个Thread.interrupted() ?
// 可以用于手动释放锁(Thread.currentThread().isInterrupted())
return Thread.interrupted();
}
非公平锁:
abstract static class Sync extends AbstractQueuedSynchronizer {
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; // state每次+1
if (nextc < 0) // overflow
throw new Error("Maximum lock count exceeded");
setState(nextc);
return true;
}
return false;
}
}
公平锁:
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;
}
}
unLock方法
release方法
public final boolean release(int arg) {
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
// waitStatus 的作用显示出来了
// waitStatus != 0 说明后面肯定有线程在排队,所以需要进行链表操作
unparkSuccessor(h);
return true;
}
return false;
}
tryRelease方法
protected final boolean tryRelease(int releases) {
// 判断独占锁线程是否为当前线程
if (!isHeldExclusively())
throw new IllegalMonitorStateException();
int nextc = getState() - releases;
boolean free = exclusiveCount(nextc) == 0;
if (free)
// 占用锁线程置为空
setExclusiveOwnerThread(null);
setState(nextc);
return free;
}
unparkSuccessor方法
private void unparkSuccessor(Node node) {
int ws = node.waitStatus;
if (ws < 0)
// 置为初始状态(0)
compareAndSetWaitStatus(node, ws, 0);
/**
* 要取消停放的线程在后继节点中,通常只是下一个节点。
* 但如果取消或明显为空,则从尾部向后遍历以找到实际未取消的继任者。
*/
Node s = node.next;
if (s == null || s.waitStatus > 0) {
// 后继节点为null 或者 waitStatus为线程取消(CANCELLED)状态
s = null;
// 循环拿到 waitStatus != CANCELLED 的节点
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
}
// 如果当前释放的头节点后面还有waitStatus != CANCELLED的阻塞节点, 则释放这个节点的线程阻塞
if (s != null)
LockSupport.unpark(s.thread);
}