美文网首页
AQS-ReentrantLock(解锁)源码浅析

AQS-ReentrantLock(解锁)源码浅析

作者: KD_ | 来源:发表于2022-03-28 11:07 被阅读0次

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);

}

相关文章

网友评论

      本文标题:AQS-ReentrantLock(解锁)源码浅析

      本文链接:https://www.haomeiwen.com/subject/bccpjrtx.html