用于循环的 Java 同步列表

2022-09-01 20:50:04

synchronizedList 上的文档指出,

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

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

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

这似乎很清楚,但我只是想确认 for each 循环是被禁止的。例如,我不能做这样的事情,对吧?

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

答案 1

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


答案 2

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

  1. 您可以围绕循环同步该块,因为在您迭代它时,列表可能会更改。
  2. 您可以使用列表作为要同步的对象,因为此类的实现会锁定自身(通过同步方法)。