美文网首页
AQS独占资源- release

AQS独占资源- release

作者: 程序员札记 | 来源:发表于2022-03-23 23:20 被阅读0次

    独占释放资源( release(int i) )

    此方法是acquire()的反操作,是独占模式下线程释放共享资源的入口。他会释放指定资源,如果彻底释放则 state = 0 ,他会唤醒等待队列里的其他线程来获取资源。这就是解锁的意义。下面是release()源码。
    为了更好理解我再次重复下上一章的知识点,AQS在判断状态时,通过用waitStatus>0表示取消状态,而waitStatus<0表示有效状态。

    public final boolean release(int arg) {
       // 尝试释放资源
       if (tryRelease(arg)) {
           Node h = head;
           // 头结点存在 且头结点状态不为0
           // 如果头结点不为初始化状态则唤醒队列下一个等待的线程
           if (h != null && h.waitStatus != 0)
               // 唤醒线程
               unparkSuccessor(h);
           return true;
       }
       return false;
    }
    

    尝试释放资源tryRelease()

    和tryAcquire()一样,这个方法时需要独占模式自定义同步器去实现的。如果是独占模式下该线程释放资源说明这个线程已经拿到资源了。直接减掉相应的资源状态即可,也不需要考虑线程安全的问题。但是release是通过tryRelease来判断是否释放过资源的,所以如果已经释放资源则应当返回true,否则返回false。
    在上上章的EasyLock中释放实现如下。

    @Override
    protected boolean tryRelease(int arg) {
        // 将当前线程清空
        setExclusiveOwnerThread(null);
        //将states设置为0
        setState(0);
        // 返回成功
        return true;
    }
    

    尝试唤醒后继线程unparkSuccessor()

    此方法用于当前线程执行完毕后唤醒后继线程来获取资源。

    private void unparkSuccessor(Node node) {
            // node为当前线程所在的结点。
            int ws = node.waitStatus;
            // 该节点状态是有效的 就将其设置为初始化状态
            if (ws < 0)
                compareAndSetWaitStatus(node, ws, 0);
            // 找到下一个需要唤醒的结点
            Node s = node.next;
            //如果为空或已取消
            if (s == null || s.waitStatus > 0) {
                s = null;
                // 从尾节点往前找。 找到有效或者初始化的点,直到找到最前面的不是node的点。
                for (Node t = tail; t != null && t != node; t = t.prev)
                    if (t.waitStatus <= 0)
                        s = t;
            }
            // 如果找的到 则唤醒该节点.
            if (s != null)
                LockSupport.unpark(s.thread);
        }
    

    也就是说 用unpark唤醒等待队列中最前的没有放弃的不是当前节点的节点线程
    至此在独占模式下的解锁和上锁功能就将讲解完成了。

    相关文章

      网友评论

          本文标题:AQS独占资源- release

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