1. FairSync 的 state & tail & head
tail:尾节点, 链表
head:头节点, 链表
state:锁状态
简单来说
lock()
1). 看看state状态,合适就拿着state直接开跑
2). 不合适就在把自己放在head链表最后
3). 首先找到自己前一个状态合格的哥们,如果前面哥们的状态是CANCELLED,那需要把这哥们从head链表中剔除掉,然后知道依次向前找到一个状态合格的哥们
4). 把找到的哥们状态置为SIGNAL,然后自己就去安心睡觉(LockSupport.park)
(最前排的哥们叫”哨兵节点“,“哑节点”)
final boolean acquireQueued(final Node node, int arg) {
boolean failed = true;
try {
boolean interrupted = false;
for (;;) {
final Node p = node.predecessor();
if (p == head && tryAcquire(arg)) {
setHead(node);
p.next = null; // help GC
failed = false;
return interrupted;
}
if (shouldParkAfterFailedAcquire(p, node) &&
parkAndCheckInterrupt())
interrupted = true;
}
} finally {
if (failed)
cancelAcquire(node);
}
}
unlock()
1). 把 state-1看看,如果>0那不好意思哥们我仍然持有当前锁,如果==0那么就把 state=0
2). 然后检查链表里的头个Node状态是非CANCELLED时,则把头节点后面的兄弟拿出来叫醒(LockSupport.unpark)
lockInterruptibly()
1). 当前线程处于LockSupport.park时,可以被interrept和unlock唤醒。lockInterruptibly()处理interrept是及时throw new InterruptedException(),而lock()只是标记一下,直到拿到锁才会Thread.currentThread().interrupt()
2. Condition firstWaiter & lastWaiter(只有持有锁的线程才有资格await(), signal()。否则抛出java.lang.IllegalMonitorStateException)
await()
1). 创建当前线程对应的Node并放入firstWaiter
2). 把当前线程持有的Lock全部释放(<=>特殊的unlock)
3). 然后从FairSync 的的链表中找出第二个节点进行LockSupport.unpark
4). 停下自己,LockSupport.park(this)
public final void await() throws InterruptedException {
if (Thread.interrupted())
throw new InterruptedException();
Node node = addConditionWaiter();
int savedState = fullyRelease(node);
int interruptMode = 0;
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
signal()
1) 从 firstWaiter链表中拿出第一个然后放到 head链表最后