gpt4 book ai didi

java - 数组的读锁

转载 作者:行者123 更新时间:2023-12-01 15:13:42 25 4
gpt4 key购买 nike

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

考虑一本名为“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 美元的价格购买 2 份 BookA。同样,行[4][5]表示Bookstore2愿意以70美元的价格出售2本。

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

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

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

来自 Bookstore1 和 Bokstore2 的数据到达两个单独的线程。目前,我将原始数据对象存储在阻塞队列中,并使用单个线程(“ProcessingThread”)来创建和修改(在更新的情况下)上述数组。

enter image description here

最后,我的客户在单独的线程(“CustomerThread”)中向我发送购买/销售书籍的订单。

典型的订单如下所示:“以 50 美元购买 3 本书 A”:

收到订单后,我会执行以下操作:

1) 检查 map 是否包含键“BookA”。

2) 如果是,那么我在持有 ReadLock (ReentrantReadWriteLock.ReadLock) 的同时克隆 BookA 的数据 (int[][])。

3)然后我迭代克隆的数据以查找价格和总数量。

我的问题是:

a)有人可以确认我不需要同步生产者(“ProcessingThread”)吗?由于 dataStorage (int[][]) 仅由“ProcessingThread”线程更改。此外,由于 dataStorage 是 volatile 的,因此当我写入它时,将建立“happens-before”(因此,“CustomerThread”将看到最新更新的数据)。

b) 是否有更好的(比使用锁更具可扩展性)方法来确保“Cu​​stomerThread”中的线程安全?我可以使用 AtomicIntegerArray 摆脱困境吗?

谢谢

最佳答案

我发现这里有点麻烦。您的数组是 volatile 的,但元素不是。由于只有一个线程修改元素,因此您是安全的。但您无法保证 CustomerThread 会看到元素更改。另外,即使元素本身是 volatile 的(不容易做到),数组也会一点一点地改变,并且 CustomerThread 很容易看到不完整的数据。

第一个解决方案是对每个数组进行适当的锁定。然后,CustomerThread 必须等待,直到完整的数组准备就绪。 (多个 CustomerThreads 可以让您解决一本书阻止其他书上的操作的问题,而且我认为这不会使您的并发问题变得更糟。)

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

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

但是,我有点担心收到多个订单的结果。如果还剩下一本书,您不想将其卖给 5 个不同的人。在我看来,从您所写的内容来看,CustomerThread 上的订单和从阻塞队列进入ProcessingThread 的信息需要仔细同步。 ProcessingThread 和 CustomerThread 都是一个线程,因此单独使用它们是没问题的。但他们可以同时做一些事情,比如减少可用书籍的数量并订购一些书籍。这两个事件需要按顺序发生,这样我们就知道谁得到了书,而正式的 Java 同步块(synchronized block)让我觉得这是最好的方法。

但你最清楚自己想要做什么(我对书店将什么样的数据放入队列感到有点困惑)。如果它没有真正回答您的问题,希望它能为您提供一些信息。

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

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com