我正在编写一个应用程序来模拟书籍市场。

考虑一本名为“ 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],其中行[0]包含价格。

row [1] ..row [4]包含每个书店可用的数量。
例如,row [1] col [0]表示Bookstore1愿意以$ 45的价格购买2份BookA。类似地,row [4] [5]表示Bookstore2愿意以$ 70的价格出售2份。

我的市场上大约有500本书,每本书的数据都存储在ConcurrentHashMap中:
ConcurrentMap<String, int[][]> map = new ConcurrentHashMap<String, int[][]>(500)

“ BookA” ----> int [] []

“ Bookn” ----> int [] []

Bookstore1和Bokstore2中的数据通过两个单独的线程到达。目前,我将原始数据对象存储在阻塞队列中,并使用单个线程(“ 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逃脱吗?

谢谢

最佳答案

我在这里有点麻烦。您的数组是易失的,但元素不是。仅需一个线程即可修改元素,因此您很安全。但是您不能保证CustomerThread将看到元素更改。同样,即使元素本身是易失性的(不容易完成),该数组也会以少量和单调形式更改,并且CustomerThread倾向于查看不完整的数据。

第一个解决方案是对每个阵列进行适当的锁定。然后,CustomerThread必须等待,直到准备好完整的数组为止。 (使用多个CustomerThreads可以解决一本书阻止其他书籍执行操作的问题,但我认为这不会使您的并发问题更加严重。)

另一个解决方案是替换整个数组,而不是修改它们。数组实际上变得不可变。从一组数据到下一组数据的更改是瞬时的,并且数据始终是一致的。现在,数组引用是易失性的事实确保了更改将立即对CustomerThread可见,而CustomerThread现在不必等待锁定。

我喜欢第二种解决方案,它回答了您的问题B。(原子往往很昂贵。如果您可以用一个原子替换一个锁,那您将领先于游戏,但是如果您要用100替换一个锁,原子,甚至只有10个,您就落后了。)

但是,我有点担心要收到多个订单。如果还剩一本书,您不想将其卖给5个不同的人。在我看来,根据您所写的内容,需要仔细同步CustomerThread上的订单和从阻塞队列进入ProcessingThread的信息。 ProcessingThread和CustomerThread都是一个线程,因此它们可以单独使用。但是他们可以同时做一些事情,例如删除可用的书籍数量并订购一些书籍。这两个事件需要顺序发生,所以我们知道谁拿到了书,而正式的Java同步块使我震惊,这是最好的方法。

但是您最清楚您要做什么(我对书店将哪些数据放入队列感到有些困惑)。希望这可以给您一些信息,如果它实际上不能回答您的问题。

关于java - 读取阵列锁定,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/11941307/

10-10 02:36