Javaの並行処理シリーズ-ReentrantLockの研究ノート

ReentrantLockの研究ノート

内部ロック形

  • フェアロックFairSyncは、新しいスレッドをグラブロックをブロックされている古いスレッドの後ろにブロックされなければなりません
  • アンフェアロックNonfairSync新しいスレッドがロックをつかむ可能性がブロックされています

デフォルトのロック形式

不公平なデフォルトのロックは、コンストラクタ残基の公正、公平なロック性能が、確かではない不公平な良好なパフォーマンスロックにそこに切り替えることができます

public ReentrantLock() {   
    sync = new NonfairSync();
}
public ReentrantLock(boolean fair) {
    sync = fair ? new FairSync() : new NonfairSync();
}

抽象内部ロック同期

ReentrantLockのは排他ロックであるので、それが公正または不当なロックロックであるかどうか、ロックモードを解除することは公平性と言うと同じロックを取得するときにということなので、同期がロックを解除しようとする方法が異なる公正をtryRelease実装標準テンプレートメソッドパターンであるサブクラスによって実装ロックtryAcquireの特定方法のロックを取得しようと試みます。また、確かに最初にロックする前にロックを取得しなければならないので、ロック法ロックを定義するので、このメソッドは抽象メソッドです

    abstract static class Sync extends AbstractQueuedSynchronizer {
        private static final long serialVersionUID = -5179523762034025860L;

        
        abstract void lock();
        //非公平的尝试获取锁
        final boolean nonfairTryAcquire(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()) {
                //多次加锁,state值增加固定值,说明了ReentrantLock是一个可重入锁
                int nextc = c + acquires;
                if (nextc < 0) // overflow
                    throw new Error("Maximum lock count exceeded");
                setState(nextc);
                return true;
            }
            return false;
        }

        protected final boolean tryRelease(int releases) {
            //ReentrantLock的可重入性导致多次释放锁就多次减去相同的值
            int c = getState() - releases;
            if (Thread.currentThread() != getExclusiveOwnerThread())
                throw new IllegalMonitorStateException();
            boolean free = false;
            if (c == 0) {
                free = true;
                setExclusiveOwnerThread(null);
            }
            //由于Thread.currentThread() != getExclusiveOwnerThread() 判断的存在,所以不需要考虑线程安全问题
            setState(c);
            return free;
        }
        
        //..........................................
        
    }

フェアロックFairSync

    static final class FairSync extends Sync {
        private static final long serialVersionUID = -3000897897090466540L;

        final void lock() {
            //公平锁的获取不会去判断state的状态,获取锁只能依赖tryAcquire的逻辑,所以公平性由tryAcquire保证
            acquire(1);
        }

        protected final boolean tryAcquire(int acquires) {
            final Thread current = Thread.currentThread();
            int c = getState();
            if (c == 0) {
                //核心点hasQueuedPredecessors(),判断当前线程前面还有没有其他线程在排队,如果有返回fasle,如果没有执行获取锁的操作
                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;
        }
    }

アンフェアロックNonfairSync

static final class NonfairSync extends Sync {
    private static final long serialVersionUID = 7316153563782823691L;
    //因为是非公平锁,所以新的阻塞节点可以和已经排队的阻塞节点一起竞争锁,而ReentrantLock又是独占锁,state状态为0说明当前所没有被持有,所以不管是新的阻塞点还是旧的阻塞点,只要state状态等于0,就可以尝试去抢占锁
    final void lock() {
        if (compareAndSetState(0, 1))
            setExclusiveOwnerThread(Thread.currentThread());
        else
            //调用AQS的方法
            acquire(1);
    }
    
    protected final boolean tryAcquire(int acquires) {
        return nonfairTryAcquire(acquires);
    }
}

要約:

ソースコードの下にまとめたように、実際には非常に簡単です:

  • 何のリターンが存在しない場合、公正かつ不公平な実装の唯一の違いは、おそらくtryAcquireメソッドを利用する必要があり、別のロックモードを取得するために公平である、それは成功したロックを取得した場合fasle、今待っている現在のスレッドの前にそこにあるものを決定する前にロックします。
  • ReentrantLockのロックを解除するリエントラント排他ロック、ロック状態値プラス1、マイナス1である、全くロックがアイドル(参照カウントのようなJVM)ではないことを示すために0であります
  • ReentrantLockのデフォルト不公平なロックは、構造パラメータで指定することができます

おすすめ

転載: www.cnblogs.com/lx-lixiao/p/12149031.html