ReentrantReadWriteLock

4459 ワード

最近javaのロックを検討したところ,読み書きロックのコードを見るとjavadocでこのクラスについての解釈が理解しにくいことが分かった.そこで自分でコードに対して理解して、ここで記録して、一部の地方はあまりはっきり見えないで、もし間違いがあれば訂正してください.
 
異なる視点からロックを見ると、ロックには以下の特性があります.
公平性:
≪フェア・ロックと非フェア・ロック|フェア・ロック|emdw≫:ロックを取得する順序がリクエスト・ロックの順序で行われている場合は、フェア・ロックです.そうでない場合は、非フェア・ロックです.
 
反発性:
排他ロックと共有ロック:排他ロックは1つのスレッドのみが保持でき、排他ロックが再ロック可能(同じスレッドで複数回取得可能)である場合、同じ一線
プログラムは複数回取得できます.
共有ロックは、複数のスレッドで取得できます.
 
ReentrantReadWriteLockは、ロックの同時性を向上させ、読み取り、読み取り、書き込み、反発を高めることができます.非公平ロックは待機時間が最も優先されます
長いその書き込みスレッドは書き込みロックを割り当てる(非公平な読み取りロックの実現によって決定される).
 
読み書きロックの公平性:
非公平リードロック:非公平リードがリードロックを取得する場合、キューヘッダノードが独占ノードであるか否かを判断し、スピン待機する.
非公平書き込みロック:非公平書き込みロックを取得する場合は、書き込みロックを直接取得してみます.
≪フェア・リード・ロック|フェア・リード・ロック|emdw≫:キューを待つヘッダ・ノードでない場合、リード・ロックは取得できません.
≪フェア・ライト・ロック|フェア・ライト・ロック|emdw≫:キューを待つヘッダ・ノードでない場合、ライト・ロックは取得できません.
 
ロックのダウングレード:
ロックのダウングレードによるロックの取得順序:
    writelock.lock();
    readlock.lock();
    writelock.unlock();
    readlock.unlock();
ロックダウングレードで書き込みロックを取得すると、スレッドがあっても読み取りロックを取得できません.データの変更が完了すると、現在のスレッドが読み取りロックを取得した後、操作を続行できます.
他の書き込みスレッドはロックを取得できないため、他の書き込みスレッドには影響されません.
 
ロックのアップグレード:
ロックのアップグレードは許可されていません.ここでソースコードを見ると困惑しますが、コードには実際にロックを取ることができます.でも、ここにある
ロックのアップグレードによってロックが取得される順序は次のとおりです.
    readlock.lock();
    writelock.lock();
    readlock.unlock();
    writelock.unlock();
 
なぜデッドロックなの?
ライトロックを取得するには、すべてのリードロックを解放する必要があるため、複数のスレッドが同時にリードロックを取得してライトロックを取得すると、ライトロックを取得する場所でリードが待機します.
ロックが解除され、デッドロックが発生します.
 
 
        //     16      , 16      
        static final int SHARED_SHIFT   = 16;
        static final int SHARED_UNIT    = (1 << SHARED_SHIFT);
        //        
        static final int MAX_COUNT      = (1 << SHARED_SHIFT) - 1;
        static final int EXCLUSIVE_MASK = (1 << SHARED_SHIFT) - 1;

        //       
        static int sharedCount(int c)    { return c >>> SHARED_SHIFT; }
        //       
        static int exclusiveCount(int c) { return c & EXCLUSIVE_MASK; }

        /**
              
         **/
        protected final boolean tryAcquire(int acquires) {
            Thread current = Thread.currentThread();
            int c = getState();
            int w = exclusiveCount(c);
            if (c != 0) {
                // (Note: if c != 0 and w == 0 then shared count != 0)
                if (w == 0 || current != getExclusiveOwnerThread())
                    return false;
                if (w + exclusiveCount(acquires) > MAX_COUNT)
                    throw new Error("Maximum lock count exceeded");
            }
            if ((w == 0 && writerShouldBlock(current)) ||
                !compareAndSetState(c, c + acquires))
                return false;
            setExclusiveOwnerThread(current);
            return true;
        }

        1. c   0,w  0,         ,       
        2. c   0,             ,   
        3.  w  0(          ),            
        4.         ,  true
        5.  c  0,  true

        
        /**
              
         **/
        protected final int tryAcquireShared(int unused) {
            Thread current = Thread.currentThread();
            int c = getState();
            if (exclusiveCount(c) != 0 &&
                getExclusiveOwnerThread() != current)
                return -1;
            if (sharedCount(c) == MAX_COUNT)
                throw new Error("Maximum lock count exceeded");
            if (!readerShouldBlock(current) &&
                compareAndSetState(c, c + SHARED_UNIT)) {
                HoldCounter rh = cachedHoldCounter;
                if (rh == null || rh.tid != current.getId())
                    cachedHoldCounter = rh = readHolds.get();
                rh.count++;
                return 1;
            }
            return fullTryAcquireShared(current);
        }
        
        1.           ,    
        2.         ,    
        3.         ,              ,        ,     
                                    ,    ,