Java 同步收集

Java 同步收集,java,loops,synchronized,Java,Loops,Synchronized,因为c已经是同步的集合,所以它是线程安全的。但是为什么我们必须在迭代中再次使用synchronized(c)?真的很困惑。谢谢 “用户必须手动同步返回的数据 在集合上迭代时: Collection c = Collections.synchronizedCollection(myCollection); ... synchronized(c) { Iterator i = c.iterator(); // Must be in the synchronized block

因为c已经是同步的集合,所以它是线程安全的。但是为什么我们必须在迭代中再次使用
synchronized(c)
?真的很困惑。谢谢

“用户必须手动同步返回的数据 在集合上迭代时:

Collection c = Collections.synchronizedCollection(myCollection);
 ...
 synchronized(c) {
     Iterator i = c.iterator(); // Must be in the synchronized block
     while (i.hasNext()) {
         foo(i.next());
     }
}
不遵循此建议可能会导致不确定性行为。”
。但是迭代必然涉及多个单独的方法调用,所以您,同步集合的用户,必须自己同步整个迭代


例如,如果没有在
c
上进行同步,则集合的内容可能会在
i.hasNext()
i.next()
之间发生变化,甚至可能从有元素变为没有更多元素,在这种情况下,
i.next()
将失败。

单独同步类上的所有方法不会使这些方法的聚合(在组中调用它们)成为线程安全的。通过将
迭代器
包装在一个同步块中,您可以保护迭代器的特定实例,使其单个方法的调用不会与多个线程的其他调用混杂在一起

如果我在安全的情况下调用
.add()
,如果我需要多次调用
.add()
来完成一个逻辑语句,则不能保证其他人没有在我的
.add()
调用之间添加或删除其他内容,除非我阻止其他所有调用
.add()
(或任何其他方法)对表示集合的变量进行同步

Iterator
对集合中的各个方法进行多次调用,它们都必须包装在一个
synchronized
块中,以使它们作为单个
事务执行
List的代码
它对底层实现进行多个单独的调用,因此它们都需要由同一线程以不间断的顺序执行才能确定

  @Override
    public Iterator<A> iterator() {
        if (tail == null)
            return emptyIterator();
    return new Iterator<A>() {
        List<A> elems = List.this;
        public boolean hasNext() {
        return elems.tail != null;
        }
        public A next() {
                if (elems.tail == null)
                    throw new NoSuchElementException();
        A result = elems.head;
        elems = elems.tail;
        return result;
        }
        public void remove() {
        throw new UnsupportedOperationException();
        }
    };
    }
@覆盖
AbstractList.Iterator()
的公共迭代器显示了进行多次调用的更复杂的逻辑


更好的包装器是将它们包装在
不可变的
集合中,然后您可以保证其他任何东西都不能改变调用之间的基础集合。

您所说的“必然涉及多个单独的方法调用”是什么意思?@user697911:
i.hasNext()
i.next()
是两个独立的方法调用,无法实现
集合。synchronizedCollection
可确保
i.hasNext()和
i.next()之间没有任何更改
。那么,concurrentHashmap将是相同的吗?我们还必须在迭代中同步concurrenthashamp吗?不,您永远不需要同步
concurrentHashmap
。CHM的文档声明:“视图的迭代器是”弱一致的“迭代器不会抛出ConcurrentModificationException,并保证遍历迭代器构造时存在的元素,并且可能(但不保证)反映构造后的任何修改。"换句话说,
ConcurrentHashMap
使用一个专门的实现,确保在迭代过程中修改映射时,其迭代器不会爆炸,并且这些迭代器可能考虑也可能不考虑进一步的修改。
ConcurrentHashMap
可以做类似的事情,因为并发是从头开始构建的;
集合。synchronizedCollection
只能为通常不并发的集合提供一个简单的包装。这是我遇到的最好的解释!