【问题标题】:Java synchronized list for loop用于循环的 Java 同步列表
【发布时间】:2011-11-12 06:03:14
【问题描述】:

有关 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();
    }
}

【问题讨论】:

  • 为什么会被禁止?生成的字节码几乎相同。 Foreach 使用迭代器...
  • 貌似synchronizedList只是用synchronized修饰了方法调用,但有局限性。也许设计者也应该装饰迭代器方法,并返回一个同步的迭代器。 for 是语言上的,不能这么容易修饰 XD:
  • 检查此链接programmerzdojo.com/java-tutorials/… 它可能会有所帮助

标签: java list collections for-loop synchronized


【解决方案1】:

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

【讨论】:

  • 如果我们从迭代器中删除项目,同时使用 hasNext()/next() 就可以了。但是,如果我们在通过 for(int : list) 循环迭代时从列表中删除某些项目 - 它会抛出 ConcurentModificationException。所以在这种情况下是不一样的。
  • @ses:但是给出的代码没有使用remove。增强的 for 循环确实使用了迭代器(用于非数组)——但这并不意味着您可以使用增强的 for 循环完成所有可以直接使用迭代器完成的操作。
  • 那是...你能在这里看看我的问题吗:stackoverflow.com/questions/16742763/…
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    【讨论】:

      【解决方案4】:

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

      【讨论】:

      • 一些格式,多说几句,它实际上可能是一个答案;]
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-06
      • 2014-07-06
      相关资源
      最近更新 更多