多个线程同时向不同步的ArrayList的对象添加元素可能会导致哪些问题?

多个线程同时向不同步的ArrayList对象添加元素可能会导致哪些问题?

What are the possible problems caused by adding elements to unsynchronized ArrayList's object by multiple threads simultaneously?

尝试使用具有多个线程的静态 ArrayList 进行一些实验,但找不到太多.

Tried to run some experiments with a static ArrayList with multiple threads but couldn't find much.

在这里,我期待在多线程环境中不同步 ArrayList 或类似对象的许多副作用.

Here i am expecting much of the side effects of not synchronizing an ArrayList or like Objects in a multithreaded environment.

任何显示副作用的好例子都将是可观的.谢谢.

Any good example showing side effects would be appreciable. thanks.

下面是我的小实验,运行顺利,无一例外.

below is my little experiment which ran smoothly without any exception.

我也想知道为什么它没有抛出任何 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);
        }
    }
}

推荐答案

在调整列表大小以容纳更多元素时,您通常会遇到问题.看ArrayList.add()

You will usually encounter issues when the list is resized to accommodate more elements. Look at the implementation of ArrayList.add()

public boolean add(E e) {
    ensureCapacityInternal(size + 1);  // Increments modCount!!
    elementData[size++] = e;
    return true;
}

如果没有同步,数组的大小将在调用 ensureCapacityInternal 和实际插入元素之间发生变化.这最终会导致 ArrayIndexOutOfBoundsException 被抛出.

if there is no synchronization, the array's size will change between the call to ensureCapacityInternal and the actual element insertion. This will eventually cause an ArrayIndexOutOfBoundsException to be thrown.

这是产生这种行为的代码

Here is the code that produces this behavior

final ExecutorService exec = Executors.newFixedThreadPool(8);
final List<Integer> list = new ArrayList<>();
for (int i = 0; i < 8; i++) {
    exec.execute(() -> {
        Random r = new Random();
        while (true) {
            list.add(r.nextInt());
        }
    });
}

相关文章