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

          關注

          壓力測試

          算法

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 96753
          • 排名 - 600

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 石城县| 顺昌县| 阿拉善左旗| 安远县| 承德县| 陈巴尔虎旗| 肥西县| 兴海县| 台东市| 东海县| 安泽县| 海林市| 仙游县| 淄博市| 信宜市| 宜宾市| 佛山市| 丰顺县| 章丘市| 大冶市| 古田县| 北海市| 桐庐县| 五寨县| 廉江市| 洱源县| 襄城县| 五大连池市| 进贤县| 大港区| 宾阳县| 醴陵市| 宜宾市| 沅江市| 山东| 营口市| 郑州市| 宣恩县| 赤峰市| 临朐县| 恩施市|