0

本の市場をシミュレートするアプリを作成しています。

次のデータを持つ「BookA」という本を考えてみましょう。

                       45   47  50  51  55    70  73  75  79 81

**Bookstore1 Buy Qty**  2   3   5   11  1   
**Bookstore2 Buy Qty**  1   3   5   1   10

**Bookstore1 Sell Qty**                       1   11  7   8  20
**Bookstore2 Sell Qty**                       2   5   2   5  10

                             **Data for BookA**

数値データはvolatile int[][] dataStorage = new int[5][10]、row[0] に価格が含まれる場所として保存されます。

row[ 1] ..row[ 4 ] には、各書店で入手可能な数量が含まれます。たとえば、row[ 1 ]col[ 0 ] は、Bookstore1 が $45 で BookA を 2 部購入する意思があることを示します。同様に、row[ 4 ][ 5 ] は、Bookstore2 が $70 で 2 部を販売する意思があることを示しています。

私の市場には約 500 冊の本があり、それぞれのデータは ConcurrentHashMap に保存されています: ( ConcurrentMap<String, int[][]> map = new ConcurrentHashMap<String, int[][]>(500))

"本A" ----> int[][]

"ブックン" ----> int[][]

Bookstore1 と Bokstore2 からのデータは、2 つの別々のスレッドで到着します。現在、生データ オブジェクトをブロッキング キューに格納し、単一のスレッド ("ProcessingThread" ) を使用して上記の配列を作成および変更 (更新の場合) します。

ここに画像の説明を入力

最後に、別のスレッド (「CustomerThread」) で書籍の購入/販売の注文を送ってくれる顧客がいます。

典型的な注文は次のようになります: 「50 ドルで BookA を 3 つ購入」:

注文を受けて、私は次のことを行います。

1) マップにキー「BookA」が含まれているかどうかを確認します。

2) はいの場合、 ReadLock (ReentrantReadWriteLock.ReadLock)を保持しながら、BookA のデータ (int[][]) を複製します。

3) 次に、複製されたデータを繰り返し処理して、価格と合計数量を見つけます。

私の質問は次のとおりです。

a)プロデューサー(「ProcessingThread」)を同期する必要がないことを誰かが確認できますか。dataStorage (int[][]) は「ProcessingThread」スレッドによってのみ変更されるためです。さらに、dataStorage は揮発性であるため、データを書き込むと "happens-before" が確立されます (したがって、"CustomerThread" には最新の更新されたデータが表示されます)。

b)「CustomerThread」でスレッドセーフを確保するためのより良い(ロックを使用するよりもスケーラブルな)方法はありますか? AtomicIntegerArray を使用して回避できますか?

ありがとう

4

1 に答える 1

1

ここで少し問題が発生しています。配列は揮発性ですが、要素はそうではありません。要素を変更するスレッドが 1 つだけなので、安全です。ただし、要素の変更が CustomerThread に表示されるという保証はありません。また、要素自体揮発性 (簡単に実行できない) であったとしても、配列は少しずつ変化し、CustomerThread は不完全なデータを参照する傾向があります。

最初の解決策は、各アレイを適切にロックすることです。次に、CustomerThread は、配列全体の準備が整うまで待機する必要があります。(複数の CustomerThreads を使用すると、1 つのブックが他のブックのアクションをブロックするという問題を回避できます。同時実行の問題が悪化するとは思いません。)

別の解決策は、配列を変更するのではなく、配列全体を置き換えることです。配列は事実上不変になります。あるデータ セットから次のデータ セットへの変更は瞬時に行われ、データは常に一貫しています。配列参照が揮発性であるという事実により、変更が CustomerThread に即座に表示されることが保証され、ロックを待つ必要がなくなりました。

私は 2 番目の解決策が好きで、むしろ質問 B に答えます。アトミック、またはわずか 10 であっても、あなたはその背後にあります。)

ただ、複数の注文が入って結果が出るのがちょっと気になる。1冊残ったら5人に売りたくない。あなたが書いたことから、CustomerThread の注文とブロッキング キューから ProcessingThread に入る情報を慎重に同期する必要があるように思えます。ProcessingThread と CustomerThread はそれぞれ 1 つのスレッドなので、個別に問題ありません。しかし、利用可能な本の数を減らして、何冊かの本を注文するなど、同時に何かを行うこともできます。これら 2 つのイベントは順番に発生する必要があるため、誰が本を手に入れるかが分かります。正式な Java 同期ブロックがそれを行うための最良の方法であると私は思います。

しかし、何をしようとしているのかは、あなたが一番よく知っています (書店がどのような種類のデータをキューに入れているのか、私は少し混乱しています)。うまくいけば、これが実際にあなたの質問に答えない場合でも、いくつかの情報が得られます.

于 2012-08-14T21:08:28.280 に答える