1. 程式人生 > >深入ReentrantLock原始碼解析

深入ReentrantLock原始碼解析

ReentrantLock是基於AQS實現的,它提供了公平鎖與非公平鎖兩種策略,當然這兩種策略都是搶佔式的。其核心程式碼是對AQS的公平、非公平的實現,下面我們來看其核心程式碼:

  1. 內部類Sync,該類定義為抽象類,並繼承自AbstractQueuedSynchronizer,它還會被NonfairSync(非公平策略)與FairSync(公平策略)兩個類繼承。主要關注nonfairTryAcquire方法與tryRelease方法

        // Sync類繼承自AbstractQueuedSynchronizer,
        abstract static class Sync extends
    AbstractQueuedSynchronizer {
    private static final long serialVersionUID = -5179523762034025860L; // ReentrantLock的lock方法就是呼叫這個方法,由子類實現。 abstract void lock(); // 這個方法提供了對非公平鎖策略的實現 final boolean nonfairTryAcquire(int acquires) { final Thread current = Thread.currentThread(); int
    c = getState(); // 只有當state為0時,才可以競爭鎖 if (c == 0) { // 與公平鎖的主要區別在這裡,下面會提供公平鎖的實現。 // 非公平鎖直接用CAS嘗試修改AQS的state,而沒考慮排隊情況,因此是不公平的 // 公平鎖只會讓處於head的執行緒去修改state,相當於排隊了,因此是公平的 // 如果state修改成功,會通過setExclusiveOwnerThread方法將當前執行緒設定為exclusiveOwnerThread,表示競爭成功
    if (compareAndSetState(0, acquires)) { setExclusiveOwnerThread(current); return true; } } // 注意,這裡實現了可重入性!這種情況是state!=0,即當前鎖是被執行緒佔有的,但是如果佔有該鎖的執行緒就是當前執行緒,那麼還是能夠修改state // 獲取到1次,state=acquires // 獲取到2次,state=2*acquires // 依次類推 // 在release的時候也會一層一層的減回去,因此要保證lock與unlock次數一樣 else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires;//這裡會state累加 if (nextc < 0) // overflow throw new Error("Maximum lock count exceeded"); setState(nextc); return true; } return false; } // 該方法提供了鎖的釋放,不論是公平還是不公平鎖,都用這個實現 // 這裡release的值與tryAcquire中acquires的值應該相等,不然會出現鎖完全釋放後,state!=0的情況,那就涼了。。。 protected final boolean tryRelease(int releases) { int c = getState() - releases; // 保證釋放鎖的執行緒,必須擁有鎖,不然丟擲異常 if (Thread.currentThread() != getExclusiveOwnerThread()) throw new IllegalMonitorStateException(); // 如果釋放完之後,state的值確實為0,那麼將獲得鎖的執行緒設定為null // 注意,這裡也支援重入性,如果釋放完之後,c不為0,那麼當前執行緒還可以繼續釋放。 boolean free = false; if (c == 0) { free = true; setExclusiveOwnerThread(null); } setState(c); return free; } // 這是對isHeldExclusively實現,即判斷當前執行緒是否exclusiveOwnerThread protected final boolean isHeldExclusively() { // While we must in general read state before owner, // we don't need to do so to check if current thread is owner return getExclusiveOwnerThread() == Thread.currentThread(); } // 對Condition的支援 final ConditionObject newCondition() { return new ConditionObject(); } // 其它方法很簡單省略... }
  2. NonfairSync,繼承自Sync,非公平鎖策略,實現很簡單,因為Sync已經都實現了非公平的策略

        static final class NonfairSync extends Sync {
            private static final long serialVersionUID = 7316153563782823691L;
    
            /**
             * 實現lock方法。先通過compareAndSetState嘗試獲取一次,如果成功則獲取鎖。
             * 否則走acquire,詳見AbstractQueuedSynchronizer原始碼解析。
             */
            final void lock() {
                if (compareAndSetState(0, 1))
                    setExclusiveOwnerThread(Thread.currentThread());
                else
                    acquire(1);
            }
    
            // 重寫tryAcquire,直接呼叫Sync的nonfairTryAcquire方法。
            protected final boolean tryAcquire(int acquires) {
                return nonfairTryAcquire(acquires);
            }
        }
  3. FairSync,繼承自Sync,公平策略。需要實現公平策略的tryAcquire

        static final class FairSync extends Sync {
            private static final long serialVersionUID = -3000897897090466540L;
    
            // 區別1:這裡沒有先嚐試獲取一次,因為公平模式必須要排隊。而非公平模式不用考慮佇列,所以可以先使用compareAndSetState獲取一次
            final void lock() {
                acquire(1);
            }
    
            /**
             * 公平鎖策略
             */
            protected final boolean tryAcquire(int acquires) {
                final Thread current = Thread.currentThread();
                int c = getState();
                if (c == 0) {
                    // 主要區別在這裡,在競爭之前,先判斷!hasQueuedPredecessors()
                    // 如果當前執行緒在隊首,則hasQueuedPredecessors返回false
                    if (!hasQueuedPredecessors() &&
                        compareAndSetState(0, acquires)) {
                        setExclusiveOwnerThread(current);
                        return true;
                    }
                }
                else if (current == getExclusiveOwnerThread()) {
                    int nextc = c + acquires;
                    if (nextc < 0)
                        throw new Error("Maximum lock count exceeded");
                    setState(nextc);
                    return true;
                }
                return false;
            }
        }