Java 同步列表 for 循环

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7335958/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 19:34:24  来源:igfitidea点击:

Java synchronized list for loop

javalistcollectionsfor-loopsynchronized

提问by user927476

Documentation on synchronizedList states that,

synchronizedList 上的文档指出,

It is imperative that the user manually synchronize on the returned list when iterating over it:

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

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

Failure to follow this advice may result in non-deterministic behavior.

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

This seems pretty clear, but I just wanted to confirm that a for each loop is prohibited. For example, I cannot do something like as follows right?

这看起来很清楚,但我只是想确认一个 for each 循环是被禁止的。例如,我不能做如下的事情对吗?

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

回答by Jon Skeet

Yes, you can - your enhanced for loop is basically the same as your code which explicitly uses the iterator. It boils down to the same code - it's just calling iterator()and then alternating between next()and hasNext()calls.

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

回答by Ryan Gross

You can do that. The foreach loop compiles to (nearly) the same bytecode as the while loop. The keys are:

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

  1. You synchronize the block around the loop because the list may change while you are iterating over it.
  2. You use the list as the object that you are synchronizing on, since the implementation of this class locks on itself (through synchronized methods).
  1. 您在循环周围同步块,因为在迭代它时列表可能会发生变化。
  2. 您将列表用作同步对象,因为此类的实现锁定了自身(通过同步方法)。

回答by John B

回答by Mike Njong

Of course you can, the only problem I see here is a performance issue, if your method dosomething()or foo(m)are costly to execute, you will have a performance cost. The size of your collection is also important to take in account while looping in a synchronized block, due to the fact that, when a thread acquire the lock, while in the synchronized block, looping in a huge collection will push other threads to wait.

当然可以,我在这里看到的唯一问题是性能问题,如果您的方法dosomething()foo(m)执行成本高昂,您将有性能成本。在同步块中循环时要考虑集合的大小也很重要,因为当线程获取锁时,而在同步块中,在巨大集合中循环将推动其他线程等待。