迭代 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 的所有线程都是
- 正在尝试添加一个新对象
- 如果添加操作 returns false,对其进行迭代以测试对象
- 永远不要执行清除或删除,集合只能增长。
根据所有这些假设,我的猜测是我不需要对 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
.
我必须迭代一个在多个线程之间共享的集合。像这样的代码:
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 的所有线程都是
- 正在尝试添加一个新对象
- 如果添加操作 returns false,对其进行迭代以测试对象
- 永远不要执行清除或删除,集合只能增长。
根据所有这些假设,我的猜测是我不需要对 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 aConcurrentModificationException
.