利用隊列同步器構建ReentrantLock

ReentrantLock即重入鎖,支持一個線程對資源重複加鎖。除此之外,該鎖還支持獲取鎖時公平性和非公平性選擇。
前面我的博客中實現的Mutex不支持重入。Synchronized關鍵字隱式支持重進入。
對於ReentrantLock,已經獲取到鎖的線程再次調用lock方法獲取鎖不被阻塞。
公平地獲取鎖就是等待時間最長地線程優先獲取鎖,鎖的獲取是順序的。
下面是公平獲取鎖和非公平獲取鎖的代碼

public static class Sync extends AbstractQueuedSynchronizer
    {

        protected final boolean tryAcquire(int acquires)
        {//以公平方式獲取鎖
            final Thread current=Thread.currentThread();
            int c=getState();
            if(c==0)
            {//此時還沒有線程獲取鎖,需要判斷加入同步隊列的當前結點是否有前驅結點,如果有線程比當前線程更早請求獲取鎖,則需要
                //等待前驅線程獲取並釋放鎖後才能繼續獲取鎖
                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 exceed");
                }
                setState(nextc);
                return true;
            }
            return false;
        }
        protected final boolean nofairTryAcquire(int acquires)
        {//非公平方式獲取鎖
            final Thread current=Thread.currentThread();
            int c=getState();
            if(c==0)
            {
                if(compareAndSetState(0,acquires))
                {
                    setExclusiveOwnerThread(current);
                    return true;
                }
            }
            else if(current==getExclusiveOwnerThread())
            {
                int nextc=c+acquires;
                if(nextc<0)
                {
                    throw new Error("Maximum lock count exceed");
                }
                setState(nextc);
                return true;
            }
            return false;
        }
        protected final boolean tryRelease(int releases)
        {
            for(;;)
            {
                int current=getState();
                int c=current-releases;
                if(Thread.currentThread()!=getExclusiveOwnerThread())
                {
                    throw new IllegalMonitorStateException();
                }
                boolean free=false;
                if(c==0)
                {//當狀態值減爲0才表示真正釋放了鎖,這時才能返回true
                    free=true;
                    setExclusiveOwnerThread(null);
                }
                if(compareAndSetState(current,c))
                    return free;
            }
        }

(1)線程再次獲取鎖。鎖需要識別獲取到鎖的線程是否爲當前佔據鎖的線程,如果是就再次成功獲取,否則就阻塞。鎖的獲取需要計數自增
(2)鎖的最終釋放。線程重複 n 次獲取了鎖,隨後在第 n 次釋放該鎖後,其他線程才能獲取到該鎖。鎖的釋放需要計數自減,當計數爲0表示鎖已經成功釋放,並返回true,否則返回false

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章