java - 关于线程安全List读时加锁的问题
巴扎黑
巴扎黑 2017-04-18 09:44:03
0
1
686

Vector或Collections.synchronizedList为什么get方法要加锁?CopyOnWriteArrayList并没有。
我觉得读的时候不加锁应该没问题吧?读时候加锁有什么意义?能确保读到最新值?那么直接给Object[] elementDatavolatile关键字保证可见性。
我也知道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);
}
巴扎黑
巴扎黑

全部回覆(1)
洪涛

Java裡面每個執行緒都有自己的工作內存,你可以理解成主內存的一部分拷貝。如果用volatile,只能保證在主記憶體上是即時可讀的,無法保證與每個執行緒的工作記憶體的原子性同步

即便不用volatile,而只是在寫入操作上加synchronized,在讀上不加,並不單單有讀不到最新值的問題,更大的問題還是線程工作內存與主存的同步,設想下面的情況:

  1. 整數i = 0

  2. a線程給i + 1

  3. 在a執行這個+1操作的同時b線程讀i到自己的工作內存,此時i仍然是0,因為沒有給讀加鎖

  4. a執行緒執行完畢,i = 1,然後同步到主記憶體

  5. b對i做+1操作,由於a已釋放了寫鎖,b可以寫,但由於自己工作內存的i是0,所以+1後i還是1

  6. b操作完畢,同步到主存,主存的i還是1。但事實上希望i是2

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板