Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2008/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在LinkedHashSet上迭代且未执行删除时跳过同步?_Java_Multithreading_Synchronization_Set_Synchronized - Fatal编程技术网

Java 在LinkedHashSet上迭代且未执行删除时跳过同步?

Java 在LinkedHashSet上迭代且未执行删除时跳过同步?,java,multithreading,synchronization,set,synchronized,Java,Multithreading,Synchronization,Set,Synchronized,我必须迭代多个线程共享的集合。类似于以下代码: 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

我必须迭代多个线程共享的集合。类似于以下代码:

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");
}
不遵循此建议可能会导致不确定性行为

但是,我也了解到LinkedHashSet提供了插入顺序迭代。我这套衣服穿一根线就够了

  • 正在尝试添加一个新对象
  • 如果add操作返回false,则对其进行迭代以测试对象
  • 切勿执行清除或删除,集合只能增长

根据所有这些假设,我的猜测是,我不需要在集合上执行同步,因为即使另一个线程在我对其进行迭代时添加了一个新对象,它也将位于集合的末尾,并且我将在到达插入点之前找到我要查找的对象

是否正确?

否,您必须同步,如中所述:

请注意,此实现未同步。如果多个线程同时访问链接的哈希集,并且至少有一个线程修改该集,则必须在外部对其进行同步

如果一个线程在另一个线程向其添加元素时对集合进行迭代,则会得到一个
ConcurrentModificationException

该类的迭代器方法返回的迭代器是快速失效的:如果在创建迭代器后的任何时间以任何方式修改集合,除了通过迭代器自己的
remove
方法之外,迭代器将抛出
ConcurrentModificationException

否,必须同步,如中所述:

请注意,此实现未同步。如果多个线程同时访问链接的哈希集,并且至少有一个线程修改该集,则必须在外部对其进行同步

如果一个线程在另一个线程向其添加元素时对集合进行迭代,则会得到一个
ConcurrentModificationException

该类的迭代器方法返回的迭代器是快速失效的:如果在创建迭代器后的任何时间以任何方式修改集合,除了通过迭代器自己的
remove
方法之外,迭代器将抛出
ConcurrentModificationException


“我猜我不需要在片场上执行同步,因为…”我会在那里阻止你。是的。如果要对集合进行修改(例如添加元素),则始终需要同步。以下是不应进行此类假设的原因。这个故事的寓意是,你不能仅仅通过你可以通过它的公共API观察到的东西来推理实现的内部工作。如果您想要无锁集合,请使用无锁集合,而不是应该同步但不同步的集合。我没有考虑使用无锁集合,谢谢您让我考虑使用ConcurrentSkipListSet。看起来很有希望“我猜我不需要在片场执行同步,因为……”我会在这里阻止你。是的。如果要对集合进行修改(例如添加元素),则始终需要同步。以下是不应进行此类假设的原因。这个故事的寓意是,你不能仅仅通过你可以通过它的公共API观察到的东西来推理实现的内部工作。如果您想要无锁集合,请使用无锁集合,而不是应该同步但不同步的集合。我没有考虑使用无锁集合,谢谢您让我考虑使用ConcurrentSkipListSet。看起来很有希望我希望他们不要强制执行这种快速失败的行为。当最后除了新对象之外什么都不可能发生时,对数组进行迭代有什么错?@Aldian这种情况不太常见,不值得处理。@Aldian:谁会说“什么都不可能发生”?您在
LinkedHashSet
周围创建了一个同步包装器,其
Iterator
甚至不知道它已被包装,从而继续保护自己免受不一致状态的影响。作为旁注,该迭代器的当前实现实际上是
LinkedHashMap$LinkedHashIterator
的一个子类型,它必须处理
LinkedHashMap
对访问时重新排序的支持,甚至与不支持插入顺序遍历的普通
HashMap
共享代码,因此,将在插入时使迭代器无效。我希望他们没有强制执行这种快速失败行为。当最后除了新对象之外什么都不可能发生时,对数组进行迭代有什么错?@Aldian这种情况不太常见,不值得处理。@Aldian:谁会说“什么都不可能发生”?您在
LinkedHashSet
周围创建了一个同步包装器,其
Iterator
甚至不知道它已被包装,从而继续保护自己免受不一致状态的影响。作为旁注,该迭代器的当前实现实际上是
LinkedHashMap$LinkedHashIterator
的一个子类型,它必须处理
LinkedHashMap
对访问时重新排序的支持,甚至与不支持插入顺序遍历的普通
HashMap
共享代码,因此,将在插入时使迭代器无效。
Set s = Collections.synchronizedSet(new HashSet());
  ...   synchronized (s) {
  Iterator i = s.iterator(); // Must be in the synchronized block
  while (i.hasNext())
      foo(i.next());  
  }