多个线程同时遍历同一个Map

8

我最近在Java中编写一个并发程序时遇到了以下困境:假设您有一个全局数据结构,它是常规非同步、非并发库(例如HashMap)的一部分。是否可以允许多个线程迭代该集合(只读取,不修改),可能在不同的交替时间内进行,即当线程1在迭代时,线程2可能正在同一地图上获取其迭代器?


如你所说,线程具有不同的迭代器。由于它们不是共享的,所以没有问题。 - Peter Lawrey
4个回答

12

没问题。能够做到这一点是创建迭代器接口的原因。每个线程在遍历集合时都有自己的迭代器实例,该实例保持其状态(例如,您正在迭代过程中的位置)。

这允许多个线程同时遍历同一集合。


7

只要没有编写者,就应该没问题。

这个问题类似于读-写锁,其中允许多个读取器从数据中读取,但在写入器“拥有”它的时间内不允许读取。多个读取器同时读取时没有并发问题。仅当至少有一个写入时,才可能出现 [数据竞争]


4

只有在尝试对数据结构进行并发修改时才会出现问题。

例如,如果一个线程正在迭代Map的内容,而另一个线程删除该集合中的元素,则您将遇到严重的问题。

如果确实需要一些线程安全地修改该集合,Java提供了机制来实现这一点,即ConcurrentHashMap。

Java中的ConcurrentHashMap?

还有Hashtable,它与HashMap具有相同的接口,但是它是同步的,尽管它的使用目前不建议(已弃用),因为当元素数量变得更大时,其性能会受到影响(与ConcurrentHashMap相比,后者不需要锁定整个集合)。

如果您恰好拥有一个未同步的集合,并且需要多个线程在其上读取和写入,则可以使用Collections.synchronizedMap(Map)获取其同步版本。


2
上述答案确实是很好的建议。一般来说,在使用并发线程编写Java代码时,只要不修改数据结构,您就不需要担心多个线程同时读取该结构。
如果将来遇到类似的问题,但全局数据结构可能会被同时修改,我建议编写一个Java类,所有线程都使用它来访问和修改该结构。该类可以实现自己的并发方法,使用同步方法或锁定。Java教程对Java的并发机制有很好的解释。我个人已经做过这个,它相当简单明了。

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