1、unlock入口
public void unlock() {
sync.release(1);
}
2、AbstractQueuedSynchronizer.release方法核心
public final boolean release(int arg) {
//arg 一直都会是1,tryRelease尝试释放锁,成功会将head节点下一个节点唤醒,进行锁竞争。
if (tryRelease(arg)) {
Node h = head;
if (h != null && h.waitStatus != 0)
unparkSuccessor(h);
return true;
}
return false;
}
3、tryRelease
protected final boolean tryRelease(int releases) {
//线程计数器-1
int c = getState() - releases;
//判断当前线程是否 == 该锁拥有者,true 执行后续,false 抛出异常。
if (Thread.currentThread() != getExclusiveOwnerThread())
throw new IllegalMonitorStateException();
boolean free = false;
//计数==0,设置该锁拥有者置null,返回true.
if (c == 0) {
free = true;
setExclusiveOwnerThread(null);
}
setState(c);
return free;
}
4、unparkSuccessor
private void unparkSuccessor(Node node) {
//cas将head节点状态置为 无状态
int ws = node.waitStatus;
if (ws < 0)
compareAndSetWaitStatus(node, ws, 0);
//判断head节点下一个接班人,是否==null or 状态是否为 1 ( CANCELLED : 因为超时或中断,该线程已经被取消 ),满足条件for循环从尾部节点向前遍历,找到head下一个节点 !=null or 状态 !>0 ,唤醒进行锁竞争;
Node s = node.next;
if (s == null || s.waitStatus > 0) {
s = null;
for (Node t = tail; t != null && t != node; t = t.prev)
if (t.waitStatus <= 0)
s = t;
} if (s != null)
LockSupport.unpark(s.thread);
}
网友评论