我在多线程环境中有一种情况没有逻辑问题,但我担心java Set的迭代器是否会在某些极端情况下中断。我不知道一段时间之后是否会崩溃:
class Bar{
AtomicLong a = 0;
AtomicLong b = 0;
public void addA(int value){
a.addAndGet(value);
}
public void addB(int value){
b.addAndGet(value);
}
}
class Foo{
Set<Bar> bars = new CopyOnWriteArraySet();
public void addBarData(Bar bar){
if (!bars.add(bar)){
for (Bar b: bars){
if (bar.equals(b)){
b.addA(bar.a);
b.addB(bar.b);
}
}
}
}
}
问题可能是如果两个线程在近时调用addBarData(barInstance),一个进入ifs body内部,并开始迭代for-each,但另一个在此时向该集添加另一个元素。 for-loop(或迭代器)会因元素数量的变化而崩溃吗?
答案 0 :(得分:2)
不,for-each循环只是一个编译器魔术,相当于用Iterator
进行集合的迭代和数组的索引。它不会添加任何其他效果,如线程安全。
答案 1 :(得分:2)
您问题中的代码看起来是线程安全的,因为:
Bar
使用AtomicLong
,它是原子和线程安全的。CopyOnWriteArraySet
也是线程安全的(它会在每次写操作时复制整个数组)。所以这一切都是线程安全的,你不会得到ConcurrentModificationException
,并且这段代码的结果是可预测的,因为你迭代的集合实际上是不可变的。