如何在迭代集合时防止嵌套的同步块

Sve*_*obs 6 java multithreading synchronization nested

在多线程Java应用程序中,我需要迭代一组对象.由于在我迭代它们时,另一个线程可以修改集合和对象,我需要使用同步.

但是不建议使用嵌套的同步块,因为它们可能导致死锁.我该如何解决这个问题?

Collection<Data> dataCollection = something.getDataCollection();

synchronized ( dataCollection ) {
  for ( final Data data : dataCollection ) {
    synchronized ( data ) {
      data.doSomething();  // doSomething() changes object state
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

Boz*_*zho 5

我认为您可以使用CopyOnWriteArrayList而不是外部同步。

ArrayList的线程安全变体,其中所有可变操作(添加,设置等)都通过对基础数组进行全新复制来实现。通常这样做的成本太高,但是在遍历操作的数量远远超过变异的情况下可能比其他方法更有效,并且在您无法或不想同步遍历但又需要防止并发线程之间的干扰时很有用


Pet*_*rey 5

您可以获取该集合的副本,并且一次只能锁定一个对象.

Collection<Data> dataCollection = something.getDataCollection();
Collection<Data> copy;
synchronized ( dataCollection ) {
  copy = new ArrayList<Data>(dataCollection);
}

for (Data data : copy) {
    synchronized ( data ) {
      data.doSomething();  // doSomething() changes object state
    }
}
Run Code Online (Sandbox Code Playgroud)