Javaの並行処理 - キューシンクロナイザ(AbstractQueuedSynchronizer)

キューシンクロナイザ(AQS)

AbstractQueuedSynchronizerキューシンクロナイザ(以下を同期と呼ぶ)、ベースフレーム同期ロックまたは他の構成要素を構築するために使用され、それが内蔵FIFOキューを介して作業キュースレッドを完了するために、メンバ変数INTが同期状態を表すリソースへのアクセスを使用します。

主な用途同期は継承シンクロナイザによって、サブクラスを継承し、同期状態を管理するための抽象メソッドを実装し、必然的に、あなたが提供するシンクロナイザを使用する必要がある、抽象メソッドの実装プロセスで同期状態に変更を加える必要がありますされます方法3(getStateを()、SETSTATE(INT NewStateに) とcompareAndSetState(INTの更新を期待INT) )彼らは状態の変化が安全であることを保証するので、動作します。サブクラス推奨のように定義されたカスタム静的内部クラス同期アセンブリ、同期自体は、任意の同期インターフェースを実装していない、それは単に同期は、両方のサポートをすることができ、供給カスタム同期成分使用方法いくつかの同期状態獲得と解放を規定します同期状態への排他的アクセスはまた、同期状態への共有アクセスをサポートすることができ、それはアセンブリの同期の異なるタイプ(ReentrantLockの、ReentrantReadWriteLockたCountDownLatchなど)を容易に可能にします。

シンクロナイザキーロック(同期コンポーネントは、任意であってもよい)であり、ロックにおいて同期を達成するための重合は、ロックは、同期セマンティクスを使用して実装されます。両者の関係を理解することができる:ロックは、ロックと相互作用するユーザ・インタフェースを定義したユーザを、直面している皮実装の詳細を、(例えば、2つのスレッドが同時アクセスを可能にすることができる)、同期がロックを向いていますロック、同期状態管理画面、スレッドラインの実装を簡素化し、実装、およびウェイクアップ基礎となるオペレーティングを待っています。ロックと同期がうまくユーザーとの懸念の実装に必要な領域を単離します。

例インターフェイスキューシンクロナイザ

シンクロナイザーのデザインは、呼び出すことによって提供されるテンプレートを同期するためのカスタム同期アセンブリおよび方法を実装するために組み合わせて、シンクロナイザ、その後、指定したユーザーのニーズを継承するために、あるテンプレートメソッドパターンに基づいて、同期メソッドをオーバーライドしていますこれらの方法は、書き換えられたメソッドのテンプレートのユーザーを呼び出します。

ときに、次の3つの方法を用いて書き換えた同期で指定されたメソッドは、アクセスを提供するか、同期状態を変更するために同期化を必要とします。

  • getStateを():現在の同期の状態を取得します。
  • SETSTATE(NewStateにINT):セットの現在の同期状態。
  • compareAndSetStateは(INT、INTの更新を期待):CASを確実にするために、現在の状態、プロセスの状態を設定するために使用されて
    設けられたアトミックを。

メソッドのシンクロナイザー書き換え可能は次のとおりです。

ここに画像を挿入説明
ここに画像を挿入説明
カスタム同期コンポーネントを実装し、同期方法によって提供されるテンプレートは、その(部分)、と呼ばれ、テンプレート方法を説明します。
テンプレートメソッド同期:
ここに画像を挿入説明
:テンプレート同期方法は、実質的に3つのカテゴリに分類提供排他取得同期状態が解除され共有取得し解放同期状態スレッド同期キュークエリを待ちますカスタム同期コンポーネントは、その同期のセマンティクスを達成するための同期方法によって提供されるテンプレートを使用します。

例:カスタム排他ロック

名前が示すように、他のスレッドがロックを獲得することができますが、ロックを取得するための唯一つのスレッド、同時に排他ロックで
同期キュー待機中、唯一のロックを解除するロック・スレッドを取得するために、後続のスレッドがロックを獲得することができるようになります

package pers.zhang.part5;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;

/**
 * @author zhang
 * @date 2020/1/20 - 17:42
 *
 * 使用AQS自定义独占锁
 */
public class Mutex implements Lock {
    //静态内部类,自定义同步器
    private static class Sync extends AbstractQueuedSynchronizer{
        //是否处于占用状态
        @Override
        protected boolean isHeldExclusively() {
            return getState() == 1;
        }

        //当状态为0的时候获取锁
        @Override
        protected boolean tryAcquire(int arg) {
            if(compareAndSetState(0, 1)){
                setExclusiveOwnerThread(Thread.currentThread());
                return true;
            }
            return false;
        }

        //释放锁,将状态设置为0
        @Override
        protected boolean tryRelease(int arg) {
            if(getState() == 0)
                throw new IllegalArgumentException();
            setExclusiveOwnerThread(null);
            setState(0);
            return true;
        }
        
        //返回一个Condition,每个condition都包含一个condition队列
        Condition newCondition(){
            return new ConditionObject();
        }
    }
    
    //将操作代理到Sync上
    private final Sync sync = new Sync();
    
    @Override
    public void lock() {
        sync.acquire(1);
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {
        sync.acquireInterruptibly(1);
    }

    @Override
    public boolean tryLock() {
        return sync.tryAcquire(1);
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return sync.tryAcquireNanos(1, unit.toNanos(time));
    }

    @Override
    public void unlock() {
        sync.release(1);
    }

    @Override
    public Condition newCondition() {
        return sync.newCondition();
    }
    
    public boolean isLocked(){
        return sync.isHeldExclusively();
    }
    
    public boolean hasQueuedThreads(){
        return sync.hasQueuedThreads();
    }
}

上記の例では、排他的ロックミューテックスは、唯一のスレッドが同時にロックを所有することができ、同期カスタムコンポーネントです。ミューテックスは、静的内部クラスを定義し、クラス内のシンクロナイザと実装排他的取得と解放の同期ステータスを継承します。tryAcquire(INT取得)方法、CAS(同期状態が1に設定されている)は、それが同期状態を取得する手段ではなく、同期状態tryRelease(INTリリース)方式でゼロにリセットした後、設定が成功した場合。直接ミューテックスを使用するユーザと内部同期取引を達成するが、ミューテックスは、ロックロック()メソッドを取得するためにミューテックスを達成するために設けられたメソッドを呼び出すことはありません、例えば、同期方式の実装で呼び出す必要が現在のスレッドのテンプレートメソッド取得(int型の引数)が大幅に信頼性の高い同期成分閾値のカスタム実装を低減する、同期のためのキュー待ちに追加される同期状態の失敗を取得するため、このメソッドを呼び出します。

公開された627元の記事 ウォンの賞賛1857 ビュー23万+

おすすめ

転載: blog.csdn.net/cold___play/article/details/104054572