同步集合

use*_*911 7 java loops synchronized

由于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());
     }
}
Run Code Online (Sandbox Code Playgroud)

不遵循此建议可能会导致非确定性行为." http://docs.oracle.com/javase/6/docs/api/java/util/Collections.

Lou*_*man 10

任何synchronized集合实现可能做的最多是保证每个单独的方法调用是同步的.但迭代必然涉及多个单独的方法调用,因此您(同步集合的用户)必须自己在整个迭代中进行同步.

例如,如果你没有进行同步c,那么集合的内容可能会在i.hasNext()和之间发生变化i.next()- 甚至可能从拥有元素到没有更多元素,在这种情况下i.next()会失败.


小智 5

使类上的所有方法单独同步不会使这些方法的线程聚合(在一个组中调用)不会安全。通过将s包装Iterator在一个同步块中,可以保护迭代器的特定实例免于被多个线程散布其单独的调用方法和其他调用的情况。

如果我.add()一次打电话是安全的,如果我需要.add()多次打电话来完成一个逻辑语句,则不能保证别人在我的两次.add()通话之间没有添加其他东西或删除了其他东西,除非我阻止其他人打电话.add()(或任何其他方法)都可以通过synchronizing代表集合的变量来实现。

Iterator使得对收集的各个方法多发来电,他们都必须被包裹在一个单一的synchronized块,使其执行作为一个单一的transaction不爽。查看实现的源代码, Iterator您将明白我的意思。这是它的源代码,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();
        }
    };
    }
Run Code Online (Sandbox Code Playgroud)

AbstractList.iterator()节目,甚至更复杂的逻辑,使多个呼叫。

更好的包装是将它们包装在Immutable集合中,然后保证在调用之间没有其他可以改变基础集合的东西。

  • 我遇到的最好的解释! (2认同)