我最近在Java中编写了一个并发程序,并遇到了一个困境:假设你有一个全局数据结构,它是常规的非同步,非并发库,如HashMap的一部分。允许多个线程在不同的交错周期内迭代整个集合(只是读取,没有修改)是否可以,即当thread2在同一个地图上获取迭代器时,thread1可能会重复一半?
答案 0 :(得分:12)
没关系。能够做到这一点是创建迭代器这样的接口的原因。迭代集合的每个线程都有自己的迭代器实例,它保持其状态(例如,您现在处于迭代过程中的位置)。
这允许多个线程同时迭代同一个集合。
答案 1 :(得分:7)
只要没有作家,它应该没问题。
此问题类似于readers-writer lock,其中允许多个读者从数据中读取数据,但在作者“拥有”锁定时不会读取数据。对于同时读取的倍数,没有并发问题。 [data race只有在您至少有一次写入时才会出现。
答案 2 :(得分:4)
只有在尝试对数据结构进行并发修改时才会出现问题。
例如,如果一个线程正在迭代Map的内容,而另一个线程从该集合中删除元素,那么您将面临严重的麻烦。
如果确实需要一些线程来安全地修改该集合,Java提供了这样做的机制,即ConcurrentHashMap。
还有Hashtable,它具有与HashMap相同的接口,但是已经同步,虽然目前不建议使用它(不推荐使用),因为当元素数量变大时它的性能会受到影响(与ConcurrentHashMap相比,它不需要锁定整个Collection)。
如果您碰巧有一个未同步的Collection并且您需要在其上面读取和写入多个线程,您可以使用Collections.synchronizedMap(Map)来获取它的同步版本。
答案 3 :(得分:2)
以上答案肯定是好建议。通常,在使用并发线程编写Java时,只要不修改数据结构,就不必担心多个线程同时读取该结构。
如果您将来遇到类似的问题,除了可以同时修改全局数据结构之外,我建议编写一个所有线程用来访问和修改结构的Java类。这个类可以使用synchronized方法或锁来实现自己的并发方法。 Java教程对Java的并发机制有很好的解释。我亲自完成了这项工作并且相当直接。