Кэш память потоков и оперативная память
Есть следующий код, поток просто добавляет числа по возрастанию в список:
List<Integer> integers = new ArrayList<>();
ListThread listThread1 = new ListThread(integers);
ListThread listThread2 = new ListThread(integers);
ListThread listThread3 = new ListThread(integers);
ListThread listThread4 = new ListThread(integers);
ListThread listThread5 = new ListThread(integers);
ListThread listThread6 = new ListThread(integers);
ListThread listThread7 = new ListThread(integers);
listThread1.start();
listThread2.start();
listThread3.start();
listThread4.start();
listThread5.start();
listThread6.start();
listThread7.start();
listThread1.join();
listThread2.join();
listThread3.join();
listThread4.join();
listThread5.join();
listThread6.join();
listThread7.join();
System.out.println(integers);
Выводится следующая ошибка:
Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: Index 171 out of bounds for length 163
at java.base/java.util.ArrayList.add(ArrayList.java:455)
at java.base/java.util.ArrayList.add(ArrayList.java:467)
Вопрос:
как я понял, у каждого потока свой кэш и у каждого в кэше хранится "своя версия" полей integers
, а сам список integers
хранится в оперативной памяти. Как тогда происходит это взаимодействие информации из кэша и информации из оперативной памяти, ведь если поток хочет положить какой-то элемент за пределы массива, то значит в кэше этого потока это массив уже увеличен. И как формируется список в нашей оперативной памяти, если в кэшах есть множество его вариантов, какой вариант попадает в оперативную память?
public class ListThread extends Thread {
private final List<Integer> list;
public ListThread(List<Integer> list) {
this.list = list;
}
@Override
public void run() {
for (int i = 0; i < 400; i++) {
list.add(i);
}
}
}