ReentrantLock源碼瞭解

    1)、ReentrantLock.tryLock
    //獲取沒有被其餘線程持有的鎖
    //1)、當沒有被任何線程持有時,首先將計數器設置爲1,並設置當前持有鎖的線程爲當前線程,最後返回true
    //2)、當被當前線程持有時,將計數器加1,最後返回true;
    //3)、不然返回false
    public boolean tryLock() {
        return sync.nonfairTryAcquire(1);
    }

    //接着直接調用抽象類中的Sync.nonfairTryAcquire
    final boolean nonfairTryAcquire(int acquires) {
        //獲取當前調用線程
        final Thread current = Thread.currentThread();
        //獲取當前鎖的狀態,也就是當前鎖的計數器的數值
        int c = getState();
        if (c == 0) {
            //此時說明,當前鎖沒有被任何線程持有
            if (compareAndSetState(0, acquires)) {
                //使用CAS操做,更新鎖的狀態,即鎖的計數器的數值,如果成功,則將當前鎖的線程持有者設置爲當前線程
                setExclusiveOwnerThread(current);
                return true;
            }
        }
        else if (current == getExclusiveOwnerThread()) {
            //根據JMM模型可知,同一個工做內存內是可見的,故同一個線程內是可見的,若相等,是同一個線程,且在同一個線程內不會發生setExclusiveOwnerThread時,在getExclusiveOwnerThread獲得的不同
            //此時說明,當前鎖的線程持有者是當前線程
            //設置鎖的計數器的值
            int nextc = c + acquires;
            if (nextc < 0) // overflow
                throw new Error("Maximum lock count exceeded");
            //更新鎖的狀態,即鎖的計數值的數值
            setState(nextc);
            return true;
        }
        return false;
    }

    2)、ReentrantLock.unlock
    //試圖釋放鎖
    //1)、當前線程不是該鎖的持有者時,拋出異常
    //2)、當前鎖的計數器更改成0時,則設置當前鎖的持有者爲null
    //3)、不然,更新當前鎖的狀態,即鎖的計數器的數值
    public void unlock() {
        sync.release(1);
    }

    //接着直接調用抽象類AbstractQueuedSynchronizer.release
    public final boolean release(int arg) {
        if (tryRelease(arg)) {
            //當鎖的狀態爲0,或者說當前鎖沒有持有者時,須要喚醒當前鎖上掛起的線程
            Node h = head;
            if (h != null && h.waitStatus != 0)
                unparkSuccessor(h);
            return true;
        }
        return false;
    }

    //再接着直接調用抽象類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) {
            //當計數器的數值爲0,說明此時鎖沒有持有者了,故先更新線程持有者,以後再去更新鎖的狀態,這樣當去獲取鎖的狀態時,此時的鎖的持有者必然是更新後的,這樣鎖的釋放和鎖的獲取就能保證一致的可見性了。
            free = true;
            setExclusiveOwnerThread(null);
        }
        //更新鎖的狀態,即鎖的計數器的數值
        setState(c);
        return free;
    }

    //直接調用AbstractQueuedSynchronizer.unparkSuccessor
    //喚醒當前節點後的第一個非取消節點中的線程
    private void unparkSuccessor(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;
            //從尾節點開始查找,直到當前節點,便可獲得一個當前節點後的第一個非取消節點
            for (Node t = tail; t != null && t != node; t = t.prev)
                if (t.waitStatus <= 0)
                    s = t;
        }

        //喚醒線程
        if (s != null)
            LockSupport.unpark(s.thread);
    }

    3)、ReentrantLock.lock
    //申請鎖
    public void lock() {
       sync.lock();
    }

    31)、非公平鎖
    //直接調用NonfairSync.lock
    final void lock() {
        //當經過CAS判斷當前鎖是否沒有持有者,如果,則直接設置當前鎖的持有者爲當前線程;
        //不然,再次嘗試加鎖,最後還不成功,就如等待隊列,線程掛起,直到被喚醒爲止
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            acquire(1);
    }

    //直接調用AbstractQueuedSynchronizer.acquire
    public final void acquire(int arg) {
        //嘗試獲取非公平鎖,當失敗時,就將當前線程入等待隊列,線程掛起,直到被掛起
        if (!tryAcquire(arg) &&
            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
            selfInterrupt();
    }

    //直接調用NonfairSync.tryAcquire
       protected final boolean tryAcquire(int acquires) {
           //嘗試獲取非公平鎖
        return nonfairTryAcquire(acquires);
    }

    //直接調用AbstractQueuedSynchronizer.addWaiter
    //將排他鎖節點添加到鏈表尾部
    private Node addWaiter(Node mode) {
        Node node = new Node(Thread.currentThread(), mode);
        // Try the fast path of enq; backup to full enq on failure
        Node pred = tail;
        if (pred != null) {
            //當前鏈表已經初始化,則CAS嘗試將排他鎖節點更改成鏈表的尾節點

            //設置當前節點的前一個節點爲當前鏈表的尾節點
            node.prev = pred;
            //當CAS嘗試更新尾節點成功,則將新尾節點的前一個節點的下一個節點更新爲新的尾節點
            if (compareAndSetTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

    //直接調用AbstractQueuedSynchronizer.compareAndSetTail
    //原子更新鏈表的尾節點
    private final boolean compareAndSetTail(Node expect, Node update) {
        return unsafe.compareAndSwapObject(this, tailOffset, expect, update);
    }

    //直接調用AbstractQueuedSynchronizer.enq
    //使用CAS原子性將節點插入到鏈表尾部
    private Node enq(final Node node) {
        for (;;) {
            Node t = tail;
            if (t == null) { // Must initialize
                //當沒有初始化時,進行頭結點與尾節點初始化,成功後,將頭結點與尾節點指向同一個處對象
                if (compareAndSetHead(new Node()))
                    tail = head;
            } else {
                //將節點插入到鏈表尾部

                //設置當前節點的前一個節點爲當前鏈表的尾節點
                node.prev = t;
                //當CAS嘗試更新尾節點成功,則將新尾節點的前一個節點的下一個節點更新爲新的尾節點
                if (compareAndSetTail(t, node)) {
                    t.next = node;
                    return t;
                }
            }
        }
    }

    //直接調用AbstractQueuedSynchronizer.acquireQueued
    //噹噹前節點爲等待隊列中的第一個節點時,獲取到鎖
    final boolean acquireQueued(final Node node, int arg) {
        boolean failed = true;
        try {
            boolean interrupted = false;
            for (;;) {
                //噹噹前節點的前節點爲頭結點,併爲當前線程嘗試獲取鎖,成功時,設置當前節點爲頭結點,並將當前節點的前節點的下一個節點取消,使之沒有被引用,這樣能夠被GC回收
                final Node p = node.predecessor();
                if (p == head && tryAcquire(arg)) {
                    setHead(node);
                    p.next = null; // help GC
                    failed = false;
                    return interrupted;
                }    
                //設置當前節點的前節點狀態爲喚醒狀態,且將當前節點掛起
                if (shouldParkAfterFailedAcquire(p, node) && parkAndCheckInterrupt())
                    interrupted = true;
            }
        } finally {
            if (failed)
                cancelAcquire(node);
        }
    }

    //直接調用AbstractQueuedSynchronizer.setHead
    //設置當前節點爲頭結點,並將當前節點的前節點置爲空,以及將當前節點持有的線程設置爲空
    private void setHead(Node node) {
        head = node;
        node.thread = null;
        node.prev = null;
    }

    //直接調用AbstractQueuedSynchronizer.shouldParkAfterFailedAcquire
    private static boolean shouldParkAfterFailedAcquire(Node pred, Node node) {
        int ws = pred.waitStatus;
        if (ws == Node.SIGNAL)
            //噹噹前節點的前節點狀態爲喚醒時,則代表下一個被執行的節點是當前節點,即線程會被喚醒
            return true;
        if (ws > 0) {
               //噹噹前節點的前節點爲取消的節點,則往前查找一個非取消的節點
            do {
                node.prev = pred = pred.prev;
            } while (pred.waitStatus > 0);
            //將查找的非取消節點的下一個節點更新爲當前節點
            pred.next = node;
        } else {
            //嘗試將當前節點的前節點的狀態設置爲喚醒狀態
            compareAndSetWaitStatus(pred, ws, Node.SIGNAL);
        }
        return false;
    }

    //直接調用AbstractQueuedSynchronizer.compareAndSetWaitStatus
       //嘗試更新節點的狀態
    private static final boolean compareAndSetWaitStatus(Node node, int expect, int update) {
        return unsafe.compareAndSwapInt(node, waitStatusOffset, expect, update);
    }

    //直接調用AbstractQueuedSynchronizer.parkAndCheckInterrupt
    //將當前線程掛起
    private final boolean parkAndCheckInterrupt() {
        LockSupport.park(this);
        return Thread.interrupted();
    }

    

 

 

Semaphore:資源控制,是線程同步的工具類,默認是公平策略;如停車場,最多隻有100個車位,故當滿時,只能出一個以後,才能進一個;
當新建時,需指定控制的資源的個數,即同時進行的線程數,還有就是使用的是公平仍是非公平的策略,默認是非公平;
acquire獲取資源;
release釋放資源;

CountDownLatch:知足條件時觸發;如賽跑,在開始前,全部運動員準備好以後,才能開始;當全部運動員到達終點時,才能結束;還如,當獲取專輯的全部視頻資源信息時,只有全部的視頻信息獲取到以後,才能進行以後的操做;當新建時,須要指定鎖計數的個數;

await:等待鎖計數爲0,以前一直阻塞
countDown:遞減計數器的計數,若是計數達到0,則釋放全部等待的線程;

實際操做都是由其屬性Sync來進行,且該屬性對象繼承了AbstractQueuedSynchronizer類;

參考資料:
http://www.itzhai.com/the-introduction-and-use-of-a-countdownlatch.html
http://mouselearnjava.iteye.com/blog/1921468
相關文章
相關標籤/搜索