Mar*_*eon 51 java concurrency synchronization arraylist
我们有多个线程调用add(obj)上ArrayList.
我的理论是,当add两个线程同时调用时,添加的两个对象中只有一个真正被添加到ArrayList.这有可能吗?
如果是这样,你怎么解决这个问题?使用同步集合Vector吗?
der*_*ion 52
当ArrayList上的两个线程同时调用add时,没有保证的行为.但是,根据我的经验,两个对象都添加得很好.与列表相关的大多数线程安全问题在添加/删除时处理迭代.尽管如此,我强烈建议不要使用带有多个线程和并发访问的vanilla ArrayList.
Vector曾经是并发列表的标准,但现在标准是使用Collections同步列表.
另外,我强烈推荐Goetz等人的Java Concurrency in Practice,如果你打算花时间在Java中使用线程.这本书更详细地介绍了这个问题.
Mat*_*ler 16
可能会发生任何事情.您可以正确添加两个对象.您只能添加其中一个对象.您可能会获得ArrayIndexOutOfBounds异常,因为未正确调整基础数组的大小.或者其他事情可能发生.我只想说你不能依赖任何发生的行为.
作为替代方案,您可以使用Vector,可以使用Collections.synchronizedList,也可以使用CopyOnWriteArrayList,或者您可以使用单独的锁.这一切都取决于你正在做什么以及你对集合的访问权限有多少.
您还可以获得实现的一个null,一个ArrayOutOfBoundsException或一些东西.HashMap已经观察到s在生产系统中进入无限循环.你真的不需要知道可能出现什么问题,只是不要这样做.
你可以使用Vector,但它往往会导致界面不够丰富.在大多数情况下,您可能会发现需要不同的数据结构.
我想出了以下代码来模拟实际情况。
并行运行100个任务,它们将完成的状态更新到主程序。我使用CountDownLatch等待任务完成。
import java.util.concurrent.*;
import java.util.*;
public class Runner {
// Should be replaced with Collections.synchronizedList(new ArrayList<Integer>())
public List<Integer> completed = new ArrayList<Integer>();
/**
* @param args
*/
public static void main(String[] args) {
Runner r = new Runner();
ExecutorService exe = Executors.newFixedThreadPool(30);
int tasks = 100;
CountDownLatch latch = new CountDownLatch(tasks);
for (int i = 0; i < tasks; i++) {
exe.submit(r.new Task(i, latch));
}
try {
latch.await();
System.out.println("Summary:");
System.out.println("Number of tasks completed: "
+ r.completed.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
exe.shutdown();
}
class Task implements Runnable {
private int id;
private CountDownLatch latch;
public Task(int id, CountDownLatch latch) {
this.id = id;
this.latch = latch;
}
public void run() {
Random r = new Random();
try {
Thread.sleep(r.nextInt(5000)); //Actual work of the task
} catch (InterruptedException e) {
e.printStackTrace();
}
completed.add(id);
latch.countDown();
}
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行该应用程序10次且至少运行3至4次时,该程序未打印正确数量的已完成任务。理想情况下,它应该打印100(如果没有例外发生)。但在某些情况下,它正在打印98、99等。
因此,可以证明ArrayList的并发更新不会给出正确的结果。
如果我将ArrayList替换为Synchronized版本,则程序将输出正确的结果。
| 归档时间: |
|
| 查看次数: |
70638 次 |
| 最近记录: |