@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.