@Test
public void testMThread() throws InterruptedException {
int count = 1500;
CountDownLatch countDownLatch = new CountDownLatch(count);
List<Integer> arrayList = new ArrayList<>();
Runnable listOperations = () -> {
arrayList.addAll(Arrays.asList(1, 2, 3, 4, 5, 6));
countDownLatch.countDown();
};
for (int i = 0; i < count; i++) {
new Thread(listOperations).start();
}
countDownLatch.await();
int size = arrayList.size();
System.out.println(size);
}
启动1500个线程,每个线程向list中添加6个元素,最后期望正确结果应该是 size = 9000,启动运行结果如下:
再多运行几次,结果又都是 9000,并非每次都能出现。看 ArrayList 源码,size 的值保存在一个成员变量中
在向集合中添加元素的时候,如果判断集合已满,就会对集合扩容
最终调用下面的方法执行扩容
private Object[] grow() {
return grow(size + 1);
}
正常结果,扩容方法会返回一个当前数组容量+1/2 容量的新数组。
但因为size、elementData两个成员变量以及扩容方法中,都没有任何同步措施,那么就可能存在,两个线程同时遇到需要扩容的情况,比如集合大小为 100,两个线程同时添加元素并扩容:
正常期望的结果是两个线程执行完,集合的 size = 102,但结果却是 101.