迭代 LinkedHashSet 时跳过同步并且没有完成删除?

Skip synchronization when iterating over a LinkedHashSet and no remove is done?

我必须迭代一个在多个线程之间共享的集合。像这样的代码:

class MyObj{}
final static Set<MyObj> instances = Collections.synchronizedSet(new LinkedHashSet<MyObj>());
// returns the same object from the set if any, or add it if not found
public MyObj test2(MyObj a){

    if(instances.add(a))
            return a;

    for(MyObj o : instances){
        if(o.equals(a))
             return o;
    }

    throw new IllegalStateException("Impossible to reach this line");
}

我已经阅读了 synchronizedSet 的 javadoc,它指出:

It is imperative that the user manually synchronize on the returned set when iterating over it:

Set s = Collections.synchronizedSet(new HashSet());
  ...   synchronized (s) {
  Iterator i = s.iterator(); // Must be in the synchronized block
  while (i.hasNext())
      foo(i.next());  
  }   

Failure to follow this advice may result in non-deterministic behavior.

但是,我还在 this answer 上读到 LinkedHashSet 提供了插入顺序迭代。我的 Set 的所有线程都是

根据所有这些假设,我的猜测是我不需要对 Set 执行同步,因为即使在我迭代它时另一个线程添加了一个新对象,它也会在 set 的末尾我会在到达插入点之前找到我要找的对象。

这是正确的吗?

不,您必须同步,如Javadoc中所述:

Note that this implementation is not synchronized. If multiple threads access a linked hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally.

如果您有一个线程迭代集合,而另一个线程向它添加元素,您将得到 ConcurrentModificationException.

The iterators returned by this class's iterator method are fail-fast: if the set is modified at any time after the iterator is created, in any way except through the iterator's own remove method, the iterator will throw a ConcurrentModificationException.