【发布时间】:2016-11-26 09:58:16
【问题描述】:
多个线程同时向不同步的ArrayList对象添加元素可能会导致哪些问题?
尝试使用具有多个线程的静态 ArrayList 进行一些实验,但找不到太多。
在这里,我期待在多线程环境中不同步 ArrayList 或类似对象的许多副作用。
任何显示副作用的好例子都将是可观的。 谢谢。
下面是我的小实验,运行顺利,无一例外。
我也想知道为什么它没有抛出任何ConcurrentModificationException?
import java.util.ArrayList;
import java.util.List;
public class Experiment {
static List<Integer> list = new ArrayList<Integer>();
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
System.out.println("A " + i);
new Thread(new Worker(list, "" + i)).start();
}
}
}
class Worker implements Runnable {
List<Integer> al;
String name;
public Worker(List<Integer> list, String name) {
this.al = list;
this.name = name;
}
@Override
public void run() {
while (true) {
int no = (int) (Math.random() * 10);
System.out.println("[thread " + name + "]Adding:" + no + "to Object id:" + System.identityHashCode(al));
al.add(no);
}
}
}
【问题讨论】:
-
因为文档状态“检测到对象的并发修改的方法可能会抛出此异常当这种修改是不允许的。” AFAIK,
ArrayList不会强制执行规则来禁止这样做。是Iterator。如果您想查看结果,请尝试在其他线程添加时从其中一个线程中删除项目,看看结果是否符合预期。现在,所有线程都只是简单地添加到列表中(并在添加后立即打印,这是此测试的最大缺陷),因此您不能指望控制台显示奇怪的结果 -
由于
System.out.println,您的线程实际上有些同步... -
Re,“尝试进行一些实验......但找不到太多。”这就是并发错误如此阴险的原因:它们有时很难重现。有时,允许线程对共享数据进行非同步访问的程序可以在几个月的测试中幸存下来,但在发布后只会在客户站点崩溃。 (别问我怎么知道的!)
-
Re, "...a static ArrayList..." 小心你的措辞。 Java 中没有静态 object 这样的东西。在您的示例中,
static是变量,而不是列表。但更重要的是,在您的示例中,重要 是列表由多个线程共享>。您不需要static变量来共享数据:这只是一种简单的方法。 -
@assylias 你给了我另一个视角。谢谢
标签: java multithreading arraylist synchronization