遍历List正在由另一个线程执行 添加/删除 操作的,这是非常不安全的。
List
这就是为什么我们需要 CopyOnWriteArrayList
CopyOnWriteArrayList
public static void main(String[] args) throws InterruptedException { List<String> list = new ArrayList<>(); Thread thread = new Thread(new Runnable() { @Override public void run() { while (true) { // java.util.ConcurrentModificationException for (String s : list) { System.out.println(s); } } } }); thread.start(); for (int i=0; i<1000; i++) { list.add("string" + i); } Thread.sleep(Long.MAX_VALUE); }
但是,如何 设置 操作。当前,以下代码不会引发任何异常。
public static void main(String[] args) throws InterruptedException { List<String> list = new ArrayList<>(); list.add("dummy"); Thread thread = new Thread(new Runnable() { @Override public void run() { while (true) { for (String s : list) { System.out.println(s); } } } }); thread.start(); for (int i=0; i<1000; i++) { list.set(0, "smart"); } Thread.sleep(Long.MAX_VALUE); }
即使没有任何意外的结果,我也想知道,如果线程仅对执行 设置 操作List,那么我们是否不使用任何锁定机制或copy n write机制是一种好习惯?
引用以下内容的javadoc ArrayList:
ArrayList
请注意,此实现未同步。如果多个线程同时访问ArrayList实例,并且至少有一个线程在结构上修改列表,则必须在外部进行同步。(结构修改是添加或删除一个或多个元素或显式调整后备数组大小的任何操作;仅 设置元素的值不是结构修改 。)
所以不,它不需要同步。