CopyOnWriteList makes the array transient which I find redundant and feel confused. According to Doug's own explanation of the volatile memory barrier, we can see that a StoreStore memory barrier is set between normal stores and volatile stores. And he explains that
StoreStore Barriers The sequence: Store1; StoreStore; Store2 ensures that Store1's data are visible to other processors (i.e., flushed to memory) before the data associated with Store2 and all subsequent store instructions. In general, StoreStore barriers are needed on processors that do not otherwise guarantee strict ordering of flushes from write buffers and/or caches to other processors or main memory.
source: http://gee.cs.oswego.edu/dl/jmm/cookbook.html
Consequently, as unlock is actually setting a volatile value to 0, all stores inside the lock should be flushed to the main memory, and can be seen by other processors. Then why again did Doug adds volatile to the array itself??
/** The lock protecting all mutators */
final transient ReentrantLock lock = new ReentrantLock();
/** The array, accessed only via getArray/setArray. */
private transient volatile Object[] array;
/**
* 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) {
final ReentrantLock lock = this.lock;
lock.lock();
try {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
} finally {
lock.unlock();
}
}