这个问题与C#和Java
有关如果你有一个未修改的集合,并且在两个线程之间共享集合引用,那么在迭代每个线程时会发生什么?
ThreadA:Collection.iterator ThreadA:Collection.moveNext ThreadB:Collection.iterator ThreadB:Collection.moveNext
threadB会看第一个元素吗?
迭代器是否在请求时始终重置?如果这是交错的会发生什么,那么movenext和item是交错的?您是否存在不处理所有元素的危险?
答案 0 :(得分:3)
它按预期工作,因为每次请求迭代器时都会得到一个新的。
如果没有,你就无法在同一个系列上做foreach,而不是foreach!
答案 1 :(得分:2)
按照惯例,实现了迭代器,以便遍历操作永远不会改变集合的状态。它仅指向集合中的当前位置,并管理迭代逻辑。因此,如果您通过N个不同的线程扫描相同的集合,一切都应该正常工作。
但是,请注意,Java的Iterator允许删除项目,而ListIterator甚至支持 set 操作。如果您希望至少使用其中一个线程使用这些操作,则可能会遇到并发问题(ConcurrentModificationException),除非Iterator专门针对此类场景设计(例如使用ConcurrentHashMap的迭代器)。
答案 2 :(得分:1)
在Java中(我也很确定在C#中),标准API集合通常没有单个迭代器。每次调用iterator()
都会产生一个新的,它有自己的内部索引或指针,因此只要两个线程都获得自己的迭代器对象,就没有问题。
但是,接口不能保证这一点,两个迭代器也不能同时工作而没有问题。对于集合的自定义实现,所有投注均已关闭。
答案 3 :(得分:0)
在c#中 - 是的,java - 似乎是,但我不熟悉。 关于c#,请参阅http://csharpindepth.com/Articles/Chapter6/IteratorBlockImplementation.aspx和http://csharpindepth.com/Articles/Chapter11/StreamingAndIterators.aspx
答案 4 :(得分:0)
至少在C#中,可以在不同的线程上同时枚举所有标准集合。但是,如果在枚举期间修改底层集合,任何线程上的枚举都会爆炸(因为它应该。)我不相信任何理智的开发人员编写集合类会让他们的枚举器以干扰枚举的方式改变集合状态,但这是可能的。但是,如果您正在使用标准集合,则可以安全地假设这一点,因此在同步集合访问时使用单个写入器/多个读取器等锁定策略。