并发链表 vs 并发链式队列

3
我需要一个并发列表,它是线程安全的,同时最适合迭代,并应返回确切的大小。 我想要储存物品的拍卖出价。因此,我希望能够:
  1. 检索物品的确切出价数量
  2. 为物品添加出价
  3. 检索给定物品的所有出价
  4. 删除物品的一项出价
我计划将其放在 ConcurrentHashMap<Item, LinkedList<ItemBid>> - LinkedList 不是线程安全的,但返回确切的大小。 ConcurrentHashMap<Item, ConcurrentLinkedQueue<ItemBid>> - concurrentlinked queue 是线程安全的,但不能保证返回确切的大小。
是否有其他更好的集合可以解决上述四点并且是线程安全的?

“Exact size” 您指的是什么意思? - bowmore
2个回答

9
在一个线程安全的集合或映射中,你无法保证大小的“一致性”,也就是说,读取和写入操作之间的“happen-before”关系不能满足你期望的使用情况,其中对大小的读取操作应该返回反映最后一次写操作的确切状态的值(注:根据下面的评论进行了改进)。
如果不考虑性能问题,您可以使用以下习语之一:
Collections.synchronizedMap(new HashMap());
Collections.synchronizedList(new ArrayList());
然后您还需要明确地同步这些对象。这将确保操作顺序始终保持一致,但代价是阻塞,并且您应该始终获得最后一个“正确”的大小。

2
线程安全的集合确立了“先行发生”关系。这是“线程安全”的重要组成部分。我认为你想说的是线程安全不可组合。也就是说,即使应用程序中的每个对象都是线程安全的,也不能保证应用程序本身是线程安全的。仅仅因为一个集合是“线程安全的”,并不能保证一个应用程序线程放入集合中的内容就是另一个应用程序线程期望在那里找到的内容。 - Solomon Slow
假设这个集合将成为一个每天处理数百万次竞标的大型拍卖系统的一部分,因此性能是一个问题。使用装饰器来同步我的集合会影响性能。 - serah
@james_large 说得好,感谢你的澄清。我回家后应该编辑一下 :) - Mena
@Kar明白了,但是你为什么需要每次都知道“精确”的尺寸呢? - Mena

2
您可以使用LinkedBlockingQueue。它是阻塞的(与CLQ相反),但大小保持不变,不像CLQ那样被扫描。

2
我向您保证,LinkedBlockingQueue 绝对是线程安全的。https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html 上面写着 BlockingQueue 的实现都是线程安全的。 - John Vint

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接