posts - 28,  comments - 15,  trackbacks - 0
          前面一節中,我們分析了ReentrantLock.lock()方法,接下來我們接著分析ReentrantLock.unlock()方法。

          1.ReentrantLock.unlock()分析

          (1)首先嘗試釋放鎖,如果要求釋放數等于鎖狀態數,那么將鎖狀態位清0,清除鎖所有者,返回true;否則返回false;
          (2)如果(1)返回的是true,說明鎖完全釋放。接下來將檢查等待隊列,并選擇一個waitStatus處于等待狀態的節點下的線程unpark(恢復),選擇的依據是從尾節點開始,選取最靠近頭節點的等待節點,同時清理隊列中線程被取消的節點;
          (3)如果(1)返回false,說明鎖只是部分釋放,當前線程仍舊持有該鎖;

           1java.util.concurrent.locks.ReentrantLock
           2 public void unlock() {
           3        sync.release(1);
           4 }

           5
           6java.util.concurrent.locks.AbstractQueuedSynchronizer
           7public final boolean release(int arg) {
           8        if (tryRelease(arg)) {   
           9            Node h = head;
          10            if (h != null && h.waitStatus != 0)
          11                unparkSuccessor(h);
          12            return true;
          13        }

          14        return false;
          15    }

          16
          17
          18 protected final boolean tryRelease(int releases) {
          19            int c = getState() - releases;   //重入鎖加鎖的次數-釋放數量
          20            if (Thread.currentThread() != getExclusiveOwnerThread())   //判斷獨占鎖是否為當前線程所有
          21                throw new IllegalMonitorStateException();
          22            boolean free = false;
          23            if (c == 0{       //加鎖次數=釋放數量
          24                free = true;
          25                setExclusiveOwnerThread(null);     //清除鎖擁有者標識
          26            }

          27            setState(c);        //設置加鎖狀態
          28            return free;
          29        }

          30
          31
          32 /**
          33     * Wakes up node's successor, if one exists.
          34     *
          35     * @param node the node
          36     */

          37    private void unparkSuccessor(Node node) {
          38        /*
          39         * Try to clear status in anticipation of signalling.  It is
          40         * OK if this fails or if status is changed by waiting thread.
          41         */

          42        compareAndSetWaitStatus(node, Node.SIGNAL, 0);    //清除頭節點signal狀態
          43
          44        /*
          45         * Thread to unpark is held in successor, which is normally
          46         * just the next node.  But if cancelled or apparently null,
          47         * traverse backwards from tail to find the actual
          48         * non-cancelled successor.
          49         */

          50        Node s = node.next;
          51        if (s == null || s.waitStatus > 0{    //等待隊列喚醒的競爭滿足FIFO,本段代碼主要是尋找最靠近頭節點的,且waitStatus為signal、condition的鏈表節點
          52            s = null;
          53            for (Node t = tail; t != null && t != node; t = t.prev)
          54                if (t.waitStatus <= 0)
          55                    s = t;
          56        }

          57        if (s != null)
          58            LockSupport.unpark(s.thread);
          59    }


          posted on 2011-08-19 15:24 zhangxl 閱讀(1859) 評論(0)  編輯  收藏 所屬分類: java 并發
          <2025年7月>
          293012345
          6789101112
          13141516171819
          20212223242526
          272829303112
          3456789

          常用鏈接

          留言簿(1)

          隨筆分類(17)

          隨筆檔案(28)

          文章分類(30)

          文章檔案(30)

          相冊

          收藏夾(2)

          hibernate

          java基礎

          mysql

          xml

          關注

          壓力測試

          算法

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 96750
          • 排名 - 600

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 龙川县| 辉县市| 靖州| 芷江| 安乡县| 甘谷县| 大余县| 遵化市| 徐闻县| 彭山县| 榆中县| 科尔| 乌鲁木齐市| 六盘水市| 安岳县| 宜君县| 咸宁市| 肇庆市| 宝丰县| 来宾市| 孟州市| 闻喜县| 大竹县| 新郑市| 东城区| 大英县| 五大连池市| 金湖县| 宾川县| 长垣县| 托克逊县| 香港| 衡阳市| 永仁县| 如皋市| 桓台县| 梅州市| 贡觉县| 太白县| 高雄县| 三原县|