该部分代码可以用现实中排队办理业务的情况来说明:
假设你排队去办理业务,队伍很长,因此除了当前正在办理业务的人,其他所有排队的人都在低头玩手机,且每个排队的人有以下三种状态:①.正常排队,且办完业务后会通知后面的人别玩手机了可以开始办理业务了。②.发现队伍过长,不排队了,走了。③.正常排队,办完业务后不通知后面的人,直接走。
此时你进入该队伍的尾部开始排队。
1.第一步,判断排队在你前面的人是否会通知你,如果会通知,那么我们就可以不用关心其他问题,在队列中待着玩手机即可。
2.第二步,如果发现排在你前面的人不排队了,要走了,那么此时我们就得往前走一位,并开始不断询问前面的人是不是也准备不排队了,直到我们排在了一个确定不会走的人后面。
3.第三步,排在你前面的人不是准备走的,但是他也不会通知你,那么你就要告诉他,一定得在办完业务后通知你。
当我们确定我们已经在队列中待好后(前置会通知我们),那么我们就可以开始休息。parkAndCheckInterrupt方法让我们的线程进入等待的状态,即休息状态。
private final boolean parkAndCheckInterrupt() {
LockSupport.park(this); //调用park()使线程进入waiting状态
return Thread.interrupted(); //如果被唤醒,查看自己是不是被中断的。
}

3.锁的释放过程
public void unlock() {
sync.release(1);
}
public final boolean release(int arg) {
if (tryRelease(arg)) { //若tryRelease后无人占用锁
Node h = head;
//获取队列的头结点h
if (h != null && h.waitStatus != 0) //若h非空,且h的waitStatus不为0
unparkSuccessor(h);
//唤醒后继
return true;
}
return false;
}
protected final boolean tryRelease(int releases) {
int c = getState() - releases; //当前state-1,得到c
if (Thread.currentThread() != getExclusiveOwnerThread()) //执行releas的不是获取锁的独占线程,抛出异常
throw new IllegalMonitorStateException();
boolean free = false; //free用来标记锁是否可获取状态
if (c == 0) {
//若state=0
free = true;
//那么当前锁是可获取的
setExclusiveOwnerThread(null); //设置当前锁的独占线程为null
}
setState(c);
//设置当前state为c
return free;
//返回锁是否是可获取状态
}
private void unparkSuccessor(Node node) {
/*
* If status is negative (i.e., possibly needing signal) try
* to clear in anticipation of signalling. It is OK if this
* fails or if status is changed by waiting thread.
*/
int ws = node.waitStatus; //获取当前线程对应节点的waitStatus
if (ws < 0)
//将当前线程对应节点waitStatus置为0
compareAndSetWaitStatus(node, ws, 0);
/*
* Thread to unpark is held in successor, which is normally
* just the next node. But if cancelled or apparently null,
* traverse backwards from tail to find the actual
* non-cancelled successor.
*/
Node s = node.next;
//获取当前线程对应节点的后继节点s
if (s == null || s.waitStatus > 0) { //若s为空或s的状态是canceled
s = null;
//将s设置为null。
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0) //此处从尾到头进行遍历,找到队列最前列的节点且状态不是Canceled,将其设置为s。但此处为何从尾部开始遍历尚未弄清楚。
s = t;
}
if (s != null)
//若上述遍历找到的s非空
LockSupport.unpark(s.thread); //调用lockSupport.unpark唤醒s对应的线程
}
release方法的逻辑仍然可以用一个办理完业务的人的后续动作来进行说明:
1.若A办理业务后无其他业务需要办理,那么表示当前业务窗口是free的。
2.A将自己的等待状态置为0,相当于退出队列。然后检查自己后面的人是否是空或者取消排队的状态。若为真,将后置设为空。
3.从队列的尾部遍历到头部,直到找到队列最前头的那个,且它的等待状态不是取消状态,那么将其唤醒,告知他可以开始办理业务了。
4.关于源码的一点疑问