• ReentrantLock锁的释放


    一:代码

     reentrantLock.unlock();

    虽然只有一句,但是源码却比较多:

    public final boolean release(int arg) {
            if (tryRelease(arg)) {
                Node h = head;
                if (h != null && h.waitStatus != 0)
                    unparkSuccessor(h);
                return true;
            }
            return false;
        }

    这个方法中各个方法意义:

    1、tryRelease(arg),尝试去解锁,通过改变state的值来释放锁,如果state的值变成了0,那么返回true,则锁释放完成,否则返回false;

    2、unparkSuccessor,如果继任的线程节点存在,就去唤醒这个继任的节点。

    二、首先调用的是sync类下的tryRelease方法 

            protected final boolean tryRelease(int releases) {
                int c = getState() - releases;
                if (Thread.currentThread() != getExclusiveOwnerThread())
                    throw new IllegalMonitorStateException();
                boolean free = false;
                if (c == 0) {
                    free = true;
                    setExclusiveOwnerThread(null);
                }
                setState(c);
                return free;
            }

    首先拿到重入的次数,释放一次重入就减少一次,只有重入的次数减少到0时,才返回true。

    三、unparkSuccessor源码:

      /**
         * Wakes up node's successor, if one exists.
         *
         * @param node the node
         */
        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) 
    			
    			// 如果头节点的ws状态与预期的一样,就把头节点的ws设置为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;
    		// 如果头节点的继任节点时空,或者被取消了,那么就不会有节点挂在这个继任节点下面,
    		// 那么就从尾部一直往前追溯,直到t.waitStatus <= 0
            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)
    		// 释放锁,令牌permit被下一个线程节点拿到。
                LockSupport.unpark(s.thread);
        }
    

      

      

  • 相关阅读:
    查看mongodb的状态
    superset----缓存之redis
    superset--presto sql
    linux----之tcpdump小用
    Git版本回退的最佳方式
    SpringBoot 热部署
    不使用Tomcat,手写简单的web服务
    Spring Security 入门
    Maven总结
    git高级用法
  • 原文地址:https://www.cnblogs.com/boywwj/p/8598945.html
Copyright © 2020-2023  润新知