是为每个迭代线程安全吗?

时间:2014-02-18 20:54:38

标签: java multithreading for-loop iterator

我在多线程环境中有一种情况没有逻辑问题,但我担心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(或迭代器)会因元素数量的变化而崩溃吗?

2 个答案:

答案 0 :(得分:2)

不,for-each循环只是一个编译器魔术,相当于用Iterator进行集合的迭代和数组的索引。它不会添加任何其他效果,如线程安全。

答案 1 :(得分:2)

您问题中的代码看起来是线程安全的,因为:

  • Bar使用AtomicLong,它是原子和线程安全的。
  • CopyOnWriteArraySet也是线程安全的(它会在每次写操作时复制整个数组)。

所以这一切都是线程安全的,你不会得到ConcurrentModificationException,并且这段代码的结果是可预测的,因为你迭代的集合实际上是不可变的。