【发布时间】:2014-01-13 02:10:45
【问题描述】:
我在工作中遇到了这个困境,想看看是否有更好的解决方案……感觉应该有一个更简单、更清晰的答案。
目标:在键级别而不是整个映射级别同时访问带有锁的映射,以确保原子性同时尽可能少地影响性能。
我有一个需要并发的 Map。 *(添加)随着时间的推移,地图将充满未知数量的条目。我有多个读者和一个作家。 writer 执行“check-then-put”,而 reader 执行简单的 get()。我需要这些是原子的……但仅限于关键级别。因此,例如,如果阅读器正在检查密钥 X,而作者正在写入密钥 Y,我不在乎是否错过了对密钥 Y 的写入。如果阅读器/编写器正在使用相同的密钥,但我需要那是原子的。
最简单的解决方案是锁定整个地图。但这似乎会影响性能,因为地图中最终会出现大约 10,000 个键。 (如果这看起来不会因为 Map 的大小相对较小而影响性能,那么我们假设 Map 有更多的键,为了争论。)
据我所知,ConcurrentHashMap 不能保证我需要的“每个键”原子行为。
想到的下一个解决方案是拥有一组锁对象。您将根据原始密钥的散列索引到锁定Object() 的数组。这仍然会有一些争论,因为您拥有的锁少于原始地图中的钥匙。我知道 ConcurrentHashMap 在后台做了类似的事情(条带化)以提供并发性(但不是原子性)。
有没有更简单的方法来执行这种类型的按键或条带锁定?
谢谢。
【问题讨论】:
-
是否提前知道所有可能的键?如果是这样,您可以在生成读取器和写入器之前为每个键分配一个锁对象。
-
@AdamBliss 我们并不提前知道所有的密钥。另外,如果我可以避免维护自己的锁对象 Map,那将是一个理想的解决方案。
-
究竟您需要哪些操作是每个键的原子操作?
ConcurrentHashMap应该在这里做正确的事。例如ConcurrentHashMap.put是原子的。 -
@LouisWasserman 我只关注推杆和接球。对于 put,我正在做一个 check-then-put,所以它不仅仅是对 put() 的调用。也许 ConcurrentHashMap 可以使用 putIfAbsent() 为我做到这一点?
-
没问题,是的。
标签: java multithreading map concurrency java-6