3

共有リソースに要素を追加しようとするプロデューサーがいるマルチスレッドアプリケーションを作成しています。プロデューサーが共有リソースで要素を生成する順序を維持したいと考えています。

たとえば、私の共有リソースは SynchronizedQueue であり、P1、P2、P3、P4 が p1、p2、p3、p4 の順序で新しい要素を生成し、その間に P5 プロデューサーがその要素をキューに追加しているため、P1、 P2、P3、P4 はロックを待機します。P5 がロックを解放すると、P1 ~ 4 のいずれかがロックを取得するため、要素の順序が失われます。

ロックを待つ要素の順序を維持する方法はありますか? 私の理解では不可能ですが、これがプログラムで達成できるかどうかを確認したいと思います。

4

6 に答える 6

1

私が考えることができる 1 つの方法PriorityPは、フィールドint priorityとを持つラッパー クラスを作成することP valueです。

int次に、各スレッドに優先順位 ( )を割り当てると、スレッドは結果としてPriorityP適切な優先順位と値を返します。

PriorityBlockingQueueこれで、 の代わりに を使用して、クラスにインターフェイスSynchronizedQueueを実装できます。ComparatorPriorityP

このようにすると、スレッドがキューに値を入力するたびに、自動的に正しい位置に配置されます。

于 2013-09-12T06:35:52.353 に答える
0

確かに可能です:) 一般に、このクラスの問題は、シーケンスがわかっている場所にシーケンス番号を追加することで解決されます。あなたの場合、プロデューサーは「P1-1」、「P1-2」、「P2-1」などのシーケンス番号を持つ製品を生産できます。これを使用して、何らかの処理後に注文を復元できます。

これは、この方法では一部の最適化が不可能なため、順序を維持するよりも望ましい方法です (たとえば、"Java reordering" を検索してください)。

次のようなことができます。

PriorityQueue priorityQueue = // give suitable comparator
int seq = 0;

void synchronized add(E e){
    priorityQueue.add(e);
}

E synchronized poll(){
    E candidate = priorityQueue.peek();
    if(candidate.getSeq() == seq){
        seq++;
        return priorityQueue.poll();
    }else{
        log.debug("{} hasn't arrived yet", seq);
        return null;
    }
}
于 2013-09-12T06:46:37.010 に答える
0

これは誤った目標です。あなたのプロデューサーはスレッドだと思います。スレッドの実行順序は厳密には定義されていません。あるときはスレッド A がスレッド B よりも速く実行され、別のときは B がより速く実行されるため、維持したい順序はランダムであり、気にする価値はありません。さらに、要素をキューに追加するのにかかる時間は非常に短いため、2 つ以上のスレッドでさえも同時に実行されるため、まったく同じ瞬間に発生していると見なすことができます。

マルチスレッドは相対論的物理学に似ています - 普遍的な時間はなく、発生する前の関係だけです。生成されたイベント間にそのような関係がある場合は、その関係を使用する必要があります。要素が共通キューに追加される時間は、そのような関係にはなりません。

于 2013-09-12T07:43:22.663 に答える
0

問題は、ロックが取得される順序が、要素が生成される順序と任意に異なる可能性があることです。これは、マルチスレッド環境でロックを取得するためにプロデューサーが自分自身をキューに入れる順序とは任意に異なる可能性さえあります。したがって、解決しようとしていたのと同じ問題が発生します。(再帰を参照)

別のレベルの間接化によってすべての問題を解決できるわけではありません ;-)

于 2013-09-12T06:56:11.927 に答える
0

共有リソースでロックがどのように取得/解放されるかを確認するためのコードは提供しませんでしたが、java.util.concurrent.locks.ReentrantLockクラスに興味があるかもしれません。

このクラスのコンストラクターは、オプションの公平性パラメーターを受け入れます。true に設定すると、競合が発生している場合、ロックは最も長く待機しているスレッドへのアクセスを許可することを優先します。

したがって、P1、P2、P3 がこの順序で再入可能ロックの取得を試み、共有リソースがロックされている場合、最も長く待機しているスレッド (この場合は P1) が最初にロックを取得し、次に P2、次に P3、次にすべてのロックを取得します。その後の他のスレッド。

于 2013-09-12T06:27:52.993 に答える