如果外部同步的ArrayList字段的字段不可变,是否安全?

让我们假设:

  1. 只有一个ArrayList
  2. 列表由多个线程访问。线程可以添加元素并遍历所有元素。
  3. 所有访问都在外部同步。因此,两个线程不可能同时访问列表。

查看ArrayList源代码,我们可以看到size和elementData字段不是可变的:

    transient Object[] elementData; // non-private to simplify nested class access

    private int size;

另外,让我们看一下add方法:

    /**
     * This helper method split out from add(E) to keep method
     * bytecode size under 35 (the -XX:MaxInlineSize default value),
     * which helps when add(E) is called in a C1-compiled loop.
     */
    private void add(E e, Object[] elementData, int s) {
        if (s == elementData.length)
            elementData = grow();
        elementData[s] = e;
        size = s + 1;
    }

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return {@code true} (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        modCount++;
        add(e, elementData, size);
        return true;
    }

这样会发生吗?

  1. 假设list有4个元素。
  2. 线程A添加了新元素。大小更新为5。
  3. 线程B添加了新元素。缓存了大小,线程B看到了它的旧值(4)。因此,最后一个元素被覆盖,而不是添加新元素。

elementData是否可能发生类似情况?