Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
196 views
in Technique[技术] by (71.8m points)

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

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

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

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.

I also wonder why it didn't throw any 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);
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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;
}

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());
        }
    });
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...