我必须迭代在多个线程之间共享的 Set。像这样的代码:
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 提供插入顺序迭代。线程对我的集合所做的所有事情就是
- 尝试添加一个新对象
- 如果添加操作返回false,请对其进行迭代以测试对象
- 永远不要执行清除或删除操作,集合只会增长。
这是正确的吗?
最佳答案
不,您必须同步,如 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 aConcurrentModificationException
.
关于java - 迭代 LinkedHashSet 时跳过同步并且未完成删除?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39334217/