循环的Java同步列表

时间:2011-09-07 14:53:24

标签: java list collections for-loop synchronized

有关synchronizedList的文档声明,

当迭代时,用户必须手动同步返回的列表:

List list = Collections.synchronizedList(new ArrayList());
...
synchronized(list) {
    Iterator i = list.iterator(); // Must be in synchronized block
    while (i.hasNext())
    foo(i.next());
}

不遵循此建议可能会导致非确定性行为。

这看起来非常清楚,但我只是想确认每个循环都禁止使用。例如,我不能做如下的事情吗?

List<MyType> list = Collections.synchronizedList(new ArrayList(<MyType>));
...
synchronized(list){
    for(MyType m : list){
        foo(m);
        m.doSomething();
    }
}

4 个答案:

答案 0 :(得分:28)

是的,您可以 - 您的增强for循环与显式使用迭代器的代码基本相同。它归结为相同的代码 - 它只是调用iterator(),然后在next()hasNext()调用之间交替。

答案 1 :(得分:1)

你可以做到这一点。 foreach循环编译为(几乎)与while循环相同的字节码。关键是:

  1. 您可以在循环周围同步块,因为在迭代时列表可能会发生变化。
  2. 您使用列表作为要同步的对象,因为此类的实现会自行锁定(通过同步方法)。

答案 2 :(得分:1)

当然,您可以,我在此处看到的唯一问题是性能问题,如果您的方法dosomething()foo(m)执行成本高,则会产生性能成本。由于当线程获得锁定时,在同步块中循环,大量集合中的循环将推动其他线程等待,因此集合的大小对于在同步块中循环时考虑也很重要。

答案 3 :(得分:0)