我查看了OpenJDK源代码的CopyOnWriteArrayList
,发现所有写操作都受到相同锁的保护,而读操作却没有任何保护。据我所知,在JMM中,对变量(读和写)的所有访问都应该受到锁的保护,否则可能出现重排序效应。
例如,set(int, E)
方法包含以下行(在锁定状态下):
/* 1 */ int len = elements.length;
/* 2 */ Object[] newElements = Arrays.copyOf(elements, len);
/* 3 */ newElements[index] = element;
/* 4 */ setArray(newElements);
另一方面,get(int)
方法仅执行return get(getArray(), index);
。
根据我对JMM的理解,这意味着如果语句1-4被重新排序为1-2(新的)-4-2(copyOf)-3,则get
可能会观察到不一致的状态数组。
我是否错误地理解了JMM,或者还有其他解释可以说明为什么CopyOnWriteArrayList
是线程安全的?