线程安全地循环通过ConcurrentHashMap而没有阻塞

时间:2019-01-16 17:02:08

标签: java concurrency thread-safety blocking

我正在研究超低延迟和高性能的应用程序。 核心是单线程的,因此不必担心并发性。

我正在开发一个计划日志功能,该功能会定期记录消息,以防止同一消息刷新到日志中。

因此,日志类包含一个ConcurrentHashMap,一个线程对其进行更新(输入新键或更新现有值),另一个线程周期性地循环遍历该映射以记录所有消息。

我担心的是,由于需要在遍历Map时记录日志,这可能会花费一些时间,这会阻止尝试更新Map的线程吗?因为我们的应用程序核心是单线程的,所以任何阻塞都是不可接受的。

除了ConcurrentHashMap之外,还可以使用其他数据结构来减少内存占用吗?

是否存在一种线程安全的方式来迭代Map而不会在只读情况下阻塞?甚至迭代过的数据可能仍然过时也是可以接受的。

2 个答案:

答案 0 :(得分:1)

根据the java API docs,它说:

  

[...]即使所有操作都是线程安全的,检索操作也不需要锁定[...]

此外,entrySet()方法文档告诉我们:

  

[返回的]设置由地图支持,因此对地图的更改会反映在该设置中,反之亦然。

这意味着可以在对地图进行迭代时修改地图,这实际上并不会阻塞整个地图。

答案 1 :(得分:0)

可能还有其他结构可以使您减少内存占用,减少延迟,并可能提供更统一和一致的性能概况。

其中一种是工作程序模式,其中您的主要工作程序发布到非阻塞队列,而记录程序从该队列中提取。这应该使两个过程脱钩,允许多个并发发布者,并允许您扩展记录器。

一种可能的数据结构是ConcurrentLinked Queue。我对Java的经验很少,所以我不确定这样做的性能概况与并发哈希图有何不同;但这是分布式系统和golang中非常普遍的模式。