Javaの並行処理の芸術(6) - Javaのロック(1)

1.ロックインタフェース

比較1.1ロックインターフェースとsynchronizedキーワード

ロックインタフェースは、以前に登場し、Javaはsynchronizedキーワードロック機能の使用を実装します。そして、Java 1.5の後に、Javaは機能に類似したsynchronizedキーワードを実装するためのロックインターフェイスとその実装クラスが追加されます。そして、同期暗黙のget /レリーズロックが異なっている、ロックインタフェースは、取得するために/リリースロック明示的である(Lock.lockを(呼び出す必要があります)、Lock.unlock()メソッド)。スレッドがロックタイムアウトを取得し、中断またロックインタフェースもロックを獲得する必要があり、ロックおよび他の同期のキーワードを取得するための非ブロックしようとすると、機能はありません。

1.2ロック用インターフェース

    Lock lock = new ReentrantLock();
    lock.lock();
    try {
        ...
    } finally {
        lock.unlock();
    }
复制代码

ロックインタフェースを使用する場合の注意事項1.3

ロック獲得処理(この時間は本当にロックし得ない)例外が発生した場合、その理由は最終的にロックをブロックにリリースされますので、●(解放するために取得していない、tryブロックでロックされてはいけませんロック失敗も)が起こります。

●ロックを取得した後に確保するために、ロックを解除することができ、finallyブロックでロックを解除します。

1.4ロックAPIインタフェース

メソッド名 説明
空ロック() 現在のスレッドがロックを取得しようとします
空lockInterruptibly()例外:InterruptedExceptionがスローされます あなたはで取得した現在のスレッドのロックを中断することができますロック、へのアクセスを遮断することができます
ブールのtryLock() それ以外の場合は、成功した場合はtrue、falseを返すメソッドがロックを取得した後にすぐに戻ります呼び出し、ロックを取得しようとする試みをノンブロッキング
ブールのtryLock(長い時間、TimeUnit unit)指定例外:InterruptedExceptionをスロー タイムアウト獲得ロック
空ロック解除() ロックを解除
条件newCondition() 待っている/通知アセンブリと現在のロックバインディング取得し、現在のスレッドが唯一のアセンブリを呼び出すためのロックは、ロックがなり、現在のスレッドを解放した後に()メソッド、呼び出しのawait()メソッドをお待ちしております

2.キュー・シンクロナイザAbstractQueuedSynchronizer(AQS)

2.1 AQS理解

AQSは、ロックまたは他の同期コンポーネントを構築するための基本的なフレームワークである、それは内蔵のFIFOキューを介して作業キュー(通常はロック糸を獲得)、スレッドを完了するためのリソースへのアクセスを同期ステータスを表すためにint型のメンバ変数を使用しています。

2.2 AQSの使用

簡単に言えば、AQSは、サブクラスおよびサブクラスによって継承される主な使用は、同期コンポーネント推奨静的内部クラスとして定義されます。AQS同期セマンティクスを使用して重合にAQS​​同期コンポーネント、。(同期コンポーネントは、単に上述したカスタムロックことが分かります)

2.3カスタマイズ同期コンポーネント(ロック)とAQS関係

ロックは、ユーザーが直面している、ロックはロックの実装の詳細を遮蔽し、呼び出すためのユーザーのためのインターフェイスを定義します。AQSは、スレッドのウェイクアップをキューイング、ロック、シールド同期状態管理の実装を簡素化し、基盤となるオペレーティング待つ実装ロックを志向します。懸念のユーザーと実装に必要なだけでなく孤立した地域をロックし、AQS。

2.4メソッド同期書き換え可能(リライタブルが彼らのニーズに応じて特定のメソッドをオーバーライド平均)

メソッド名 説明
保護されたブールtryAcquire(int型引数) このメソッドを実装するための独占獲得同期状態、彼らはCASを満たしていれば、新たな状態に設定され、同期ステータスを照会し、それが期待を満たしているかどうかを判断する必要があります。
保護されたtryRelease(int型の引数) 独占リリース同期ステータス。
保護されたint型tryAcquireShared(int型引数) コンプライアンス値が0以上である場合に取得同期状態を共有し、それは同期状態の成功を取得し、そうでなければ失敗します。
保護されたブールtryReleaseShared(int型引数) リリース同期ステータスを共有しました。
保護されたブールisHeldExclusively() 現在の同期状態が排他モードで取得されているかどうか。

によって提供される2.5同期メソッドテンプレート

メソッド名 説明
無効取得(int型引数) 独占は同期して取得します。メソッドの戻りが成功する場合は取得に失敗した場合は、スレッド同期キューが入るのを待っています。加えて、この方法は、オーバーライドされたtryAcquire(INT引数)メソッドを呼び出します。
無効acquireInterruptibly(int型引数) このメソッドはvoid取得(int型引数)メソッド割り込み応答バージョンです。同期キューのスレッドに割り込まとInterruptedExceptionある例外をスローすることができます。
ブールtryAcquireNanos(int型の引数、長いまたはnanos) このメソッドはvoid acquireInterruptibly(int型の引数)メソッドのタイムアウト待ちのバージョンです。
無効acquireShared(int型引数) 取得同期ステータスを共有し、排他的な主な違いを得ることは、一度に複数のスレッドが同期して取り戻すことができます。
無効acquireSharedInterruptibly(int型引数) このメソッドはvoid acquireShared(int型引数)メソッド割り込み応答バージョンです。
ブールtryAcquireSharedNanos(int型の引数、長いまたはnanos) このメソッドはvoid acquireSharedInterruptibly(int型の引数)メソッドのタイムアウト待ちのバージョンです。
ブールリリース(int型引数) 独占リリース同期ステータス。この方法は、tryRelease(int型引数)メソッド書き換え呼び出されます。
ブールreleaseShared(int型引数) リリース同期ステータスを共有しました。
コレクション<スレッド> getQueueThreads() 同期キューで待機しているスレッドのコレクションを取得します。

2.5シンクロナイザ実装

同期がテンプレート設計パターンに基づいてされるように設計された後、静的内部クラスで、すなわちカスタム同期コンポーネントは、指定されたメソッドを書き換える、AQSを継承します。テンプレートメソッドでシンクロナイザは、カスタム同期コンポーネントの呼び出し、呼び出しオーバーライドされたメソッドでテンプレートメソッドになります。

class Mutex implements Lock{
    //静态内部类,自定义同步器
    private static class Sync extends AbstractQueueSynchronizer{
        //是否处于占用状态
        protected boolean isHeldExclusively(){
            return getState() == 1;
        }
        //当状态为0的时候获取锁
        public boolean tryAcquire(int acquires){
            if(compareAndSetState(0,1)){
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }
        //释放锁,将状态设置为0
        protected boolean tryRelease(int release){
            if(getState() == 0)throw new IllegalMonitorStateException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        //返回一个Condition,每个condition都包含了一个condition队列
        Condition newCondition(){
            return new Condition();
        }
    }
    //仅需要将操作代理到Sync上即可
    private final Sync sync = new Sync();
    public void lock(){sync.acquire(1)};
    public boolean tryLock(){
        return sync.tryAcquire(1);
    }
    public void unlock(){
        sync.release(1);
    }
    public Condition newCondition(){
        return sync.newCondition();
    }
    public boolean isLocked(){
        return sync.isHeldExclusively();
    }
    public boolean hasQueuedTreads(){
        return sync.hasQueuedTreads();
    }
    public void lockInterruptibly() throws InterruptedException{
        sync.acquireInterruptibly(1);
    }
    public boolean tryLock(long timeout,TimeUnit unit) throws InterruptedException{
        return sync.tryAcquireNanos(1,unit.toNanos(timeout));
    }
}
复制代码

おすすめ

転載: juejin.im/post/5cf9bb6c51882512a675f9b0