3

Java Concurrency in Practiceを読んだところ、次の質問が残っています: ConcurrentHashMap を使用する場合、本の第 1 部で説明されているデータの同時実行の問題について、まだ心配する必要がありますか? 以下は、私のプログラムの 1 つからの例です。

1. トレーダーの現在のポジション(「整数」が数学用語である共有整数)

この数値は、traderオブジェクトが現在所有しているものを表し、その状態を定義します。何をすべきかを知るために、その位置を読み取る必要があります (新しい位置を開始するか、現在の位置を管理するかを調べます)。 Traderメソッドは独自のスレッドで実行されます。

brokerオブジェクトは の位置の設定を担当しますtrader。トレーダーの注文の 1 つが約定されるたびにポジションが設定されます。 Brokerメソッドは独自のスレッドで実行されます。

traderとの両方がbroker同じパッケージに入っています。位置は package-private として実装されていますstatic ConcurrentHashMap。キーはトレーダー オブジェクトの ID です。値は整数です。

パッケージの外部はアプリケーションです。public getter を使用してトレーダーのポジションを間接的に取得します。

位置はせいぜい数分に 1 回しか変化しないため、broker頻繁にマップに触れることはありません。ただし、traderアプリケーションは頻繁に読み取ります。さらに、複数のトレーダーが同時にマップを読んでいることがよくあります。

このように ConcurrentHashMap を使用すると、ロックやデータの可視性について作業する必要がなくなりますか? ConcurrentHashMap がすべてを処理しますか?

2. 市場 (ビッド、アスク、最終価格)

ポジションとほぼ同じ状況brokerですが、非常に頻繁に価格が更新されます (繁忙期には 1 秒間に最大 10 回、通常は 1 秒間に数回)。およびアプリケーションはtrader、依然として頻繁に読み取りを行います。マップ キーは現在、どの株または先物かを示すコードであり、値は市場価格を保持するオブジェクトです。

問題なく動作しているように見えますが、JCIP を読んだ後、正しく実装されていないとプログラムが壊れる可能性があることに気付きました。この本は ConcurrentHashMap について語っていますが、手動で対処する必要がなくなったパート I の問題については明示的に教えていません。この場合、何もする必要はないようです。synchronizeあれは正しいですか?

4

3 に答える 3

4

このように ConcurrentHashMap を使用すると、ロックやデータの可視性について作業する必要がなくなりますか? ConcurrentHashMap がすべてを処理しますか?

これは、マップの内容によって異なります。例を正しく読むと、状況は次のようになります

static final ConcurrentMap<Integer,Integer> map = ...

class Trader{

  public int doRead(){
      map.get(someId);
   }
}
class Broker{
   public void doWrite(){
      map.put(someId,someValue);
   }
}

その場合、はい、すべての同時実行が処理されます。

ただし、マップが次のように見える場合

static final ConcurrentMap<Integer,Trader> map = ..

    class Broker{
       public void doWrite(){
          map.get(someId).setPosition(somePosition);
       }
    }

これはスレッド セーフではありません。ConcurrentHashMap は配置時にロックされますが、この時点でのオブジェクトの同時アクセスはすべて、独自の同期を処理する必要があります。

于 2010-12-29T18:54:17.030 に答える
4

はい、次の場合ConcurrentHashMapに限り、可視性とロックを処理します。

  • map が保持する値は不変です。あなたの価格オブジェクトが不変であることを考えると、あなたの説明では真実のようです。
  • アトミックである必要があり、マップのAPIへの単一の呼び出しとして表現できないマップ上の操作はありません。たとえば、「マップから値を読み取り、計算を実行し、結果をマップに戻す」などの操作をアトミックにする必要がある場合でも、この操作中に明示的なロックを保持する必要があります。などのマップ API のアトミック操作を使用しますget/put/putIfAbsent
于 2010-12-29T18:41:19.363 に答える
3

毎秒 100,000 を超える更新/読み取り (非常に大まかなガイド) について話している場合を除き、複数のスレッドの使用は考慮しません。その理由は、スレッドセーフなコンポーネントはそうでないコンポーネントより何倍も時間がかかるからです。したがって、コンポーネントがスレッド セーフになるまでに 5 倍の時間がかかる場合は、5 を超えるスレッドを同時に使用してブレーク イーブンにする必要があります。

複数のスレッドは、比較的コストのかかる操作を実行する場合に非常に役立ちます。ポジションまたは価格の更新は、1 つのスレッドとしてはるかに効率的です。

于 2010-12-29T21:06:55.740 に答える