Javaは選択同期を実現

私は、同じパラメータを持つ2つのスレッドが実行され、競合が発生するアプリケーションの問題に直面しています。 1つの解決策は、同期化されたブロックを使用することでしたが、問題は同一のパラメータを持つスレッドに対してのみ発生するため、非常に非効率的です。私が考えた1つの方法は、パラメタの組み合わせをキーとして、オブジェクトを値として格納するための同時マップを使用することでした。スレッドが操作を開始するたびに、マップにキーが含まれているかどうかを確認し(paramの組み合わせ)その組み合わせのために格納されたオブジェクトを待機します。スレッドは最後にこのオブジェクトをマップから削除し、そのオブジェクトに対してnotifyを呼び出します。このアプローチの問題は、同じパラメータ組み合わせに対して同じオブジェクトを生成することです。例:thread1がマップに挿入され、notifyとremoveを呼び出すと、thread2が待ち状態になることがありますが、オブジェクトがマップから失われても、他のスレッドは出てこないでしょう。

この問題に対するエレガントなアプローチはありますか?

0
@ Thor84問題は私が維持している古いコードです、 stackoverflow.com/questions/7888764 /…
追加された 著者 Rnet,
@ Thor84noいいえ、あなたがそのスレッドを密接に見るならば、非常に投票された解決策は、私がその質問をする前にやったかもしれないデータベースに操作を引き継ぐことを提案します、私が尋ねた理由は、既存のコードを変更し、スレッドを使用して回避することができます。私がこの質問から得たいと思ったのは、待っている以外に別のアプローチがあるかどうかを知ることでした。
追加された 著者 Rnet,
@ Thor84no Fine、それは正しいことでした。私はちょうどスレッドにのみ問題を抽象化し、java.util.concurrentの機能を使っていろいろなアプローチが存在するかどうかを見てみました
追加された 著者 Rnet,
追加された 著者 irreputable,
競合が同じパラメータで実行されている場合にのみ、競合が発生するのはなぜですか?コードを投稿できますか?
追加された 著者 Thor84no,
だから、私はこれをまっすぐにしましょう。あなたはすでに前にこの質問をしていますが、投票したいくつかのまともな回答があります。なぜこれらがあなたの問題を解決しないのか、今度はもっと良い結果が得られると言っても意味がありません。
追加された 著者 Thor84no,
私はスレッドを密接に読んだが、なぜそれがあなたにとって十分ではなかったのかについて何も言わなかった。問題の事実は、彼らはおそらく正しいですし、最善の解決策です。だからあなたがそれに反応しないとき、あなたはより良い選択肢を得るためにどのように期待していますか?あなたがしなければならないことは、あなたがデータベースでそれをやりたいと思わなかったことと、新しい質問を開くのではなく、その質問の理由を伝えることです。
追加された 著者 Thor84no,

3 答え

パラメータの組み合わせのプールを作成します。 1つのスレッドが実行中であることを保証する必要があるたびに、 Pool.acquire(params)を呼び出します。

このように使用してください:

素晴らしい hashCode equals を使用してオブジェクトのパラメータをラップします。

スレッドでは:

synchronized(pool) {
  pool.acquire(myParams);
}
// do the work
synchronized(pool) {
  pool.release(myParams);
}

プール:

class Pool {
  Set lockedParams;

 //In Pool - note that this is synchronized!
  void acquire(Params params) {
    Params lock = lockedParams.get(params);
    if(lock != null) {
     //Locked by another thread
      lock.wait();
    }
    lockedParams.add(params);
  }

  void release(Params params) {
    Params lock = lockedParams.remove(params);
    lock.notifyAll();
  }
}

それは一つのアイデアです。 finally に実際のケース( release())のエラー処理を追加する必要があります。この場合、 Pool < .release()など)。

0
追加された
wait()はすべてのモニタを解放し、スレッドが起動すると再獲得されます。 Thor84noは、 acquire() release()の両方が単一の synchronized ブロックにラップされた古いバージョンを指していたと思います
追加された 著者 Konrad Garus,
異なるパラメータを使用している場合、 synchronized(プール)ブロック(作業が完了した場所)内の複数のスレッドを許可する方法はありますか?
追加された 著者 Thor84no,
私は、このアイデアは一意のParamsにのみ並列スレッドを許可するスレッドプールだと思います。重複したParamsがスレッドを取得しようとすると、現在実行中の(重複している)Paramsが完了するまでブロックされます。あなたが提案したようにいくつかの問題があるように思えます。すなわち、acquire()でwait()した場合、プールから他のスレッドを取得することはできません。私は、スキームが異なって実装されているので、うまくいくと確信しています。
追加された 著者 sceaj,

notify ではなく notifyAll を呼び出して、待機中のすべてのスレッドに通知します。なぜマップから同期オブジェクトを削除したいのですか?そのオブジェクトのロックを取得しようとします。スレッドが成功した場合はクリティカルセクションに入り、それ以外の場合は待機します。

その待ち時間にタイムアウトを追加することができます。したがって、スレッドが一定期間ロックを取得できない場合は、失敗します。このようにして、コードはデッドロックにはなりません。

0
追加された

パラメータ(またはそれらのサブセット)を文字列として表すことができる場合は、 interned 文字列で同期することができます。

0
追加された