Vector或Collections.synchronizedList为什么get方法要加锁?CopyOnWriteArrayList并没有。
我觉得读的时候不加锁应该没问题吧?读时候加锁有什么意义?能确保读到最新值?那么直接给Object[] elementData
加volatile
关键字保证可见性。
我也知道CopyOnWriteArrayList修改是每次重新建一个elementData
,但就算不是重新建,读时不加锁有什么问题?请赐教。
//以下是CopyOnWriteArrayList的代码:
@SuppressWarnings("unchecked")
private E get(Object[] a, int index) {
return (E) a[index];
}
/**
* {@inheritDoc}
*
* @throws IndexOutOfBoundsException {@inheritDoc}
*/
public E get(int index) {
return get(getArray(), index);
}
//以下是Vector的代码:
public synchronized E get(int index) {
if (index >= elementCount)
throw new ArrayIndexOutOfBoundsException(index);
return elementData(index);
}
Java裡面每個執行緒都有自己的工作內存,你可以理解成主內存的一部分拷貝。如果用volatile,只能保證在主記憶體上是即時可讀的,無法保證與每個執行緒的工作記憶體的原子性同步
即便不用volatile,而只是在寫入操作上加synchronized,在讀上不加,並不單單有讀不到最新值的問題,更大的問題還是線程工作內存與主存的同步,設想下面的情況:
整數i = 0
a線程給i + 1
在a執行這個+1操作的同時b線程讀i到自己的工作內存,此時i仍然是0,因為沒有給讀加鎖
a執行緒執行完畢,i = 1,然後同步到主記憶體
b對i做+1操作,由於a已釋放了寫鎖,b可以寫,但由於自己工作內存的i是0,所以+1後i還是1
b操作完畢,同步到主存,主存的i還是1。但事實上希望i是2