【问题标题】:Slow interation over a ReadWriteLock protected map: read lock, concurrent map or copying?对受读写锁保护的映射进行缓慢迭代:读锁、并发映射还是复制?
【发布时间】:2023-03-21 02:11:01
【问题描述】:

我有一张经常阅读但很少写入的地图。有些操作(可以是读或写)涉及多个对象,需要原子操作,所以我使用了 ReadWriteLock 来提高性能。

现在我可以选择将并发映射降级为普通哈希映射,但我担心一些缓慢的迭代代码。

如果我降级地图,长迭代器必须持有读锁以避免并发访问异常。我认为这会阻塞写入线程太久。

由于一些迭代器对不一致的数据不敏感,我可以保留并发映射,以便迭代器可以与并发写入一起使用。但是,这会为正确使用锁的操作增加不必要的开销(来自并发映射)。

或者,我可以实现类似 Read-on-write 映射,其中克隆整个(非并发)映射以进行写入操作,以便现有迭代器继续在读锁之外工作。

显然,所有这些方法都是有效的,性能取决于实际代码和设置。但是,我想知道有没有这方面的研究(所以我不必自己做实验)?

【问题讨论】:

标签: java concurrency concurrent-collections


【解决方案1】:

我有一张经常阅读但很少写入的地图。

在这种情况下,我会考虑实现写映射的副本。例如

private final Map<Key, Value> map = ?* thread safe map */
private volatile Map<Key, Value> mapCopy = emptyMap();

// when you write
get lock
modify map
take a copy and store it in mapCopy
release lock

// when you read
Map<Key, Value> map = this.mapCopy;
use map

如您所见,您永远不需要在读取时获得锁定,只需在写入时获得。

如果我降级地图,长迭代器必须持有读锁以避免并发访问异常。我认为这会阻塞写入线程太久。

我建议你测量一下,而不是猜测。

我想知道有没有这方面的研究

如果确实如此,我不会太认真地对待这样的研究。正如您所建议的,结果会因您的情况而异。

【讨论】:

  • 我希望有人做一些研究,比如当地图大小这么大并且访问模式是这样的时候,那么实现的性能就是这样,但也许我要求太多了。我同意你的观点,即写时复制地图似乎效率更高。
  • CopyOnWriteArrayXxxx 集合使用这种方法。在考虑地图大小时,您需要查看键和值的复杂性,例如它们是否需要深度复制?
  • 如果您觉得有用,可以将这样的报告作为文章发表。 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多