検索

ホームページ  >  に質問  >  本文

java - 关于线程安全List读时加锁的问题

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);
}
巴扎黑巴扎黑2809日前668

全員に返信(1)返信します

  • PHP中文网

    PHP中文网2017-04-18 09:46:03

    Java の各スレッドには独自の作業メモリがあり、これはメイン メモリのコピーとして理解できます。 volatile を使用した場合、メイン メモリ上で即座に読み取れることのみが保証され、各スレッドの作業メモリとのアトミックな同期は保証されません

    volatile を使用せず、書き込み操作に synchronized を追加するだけで読み取り操作には追加しない場合でも、最新の値を読み取れないという問題だけでなく、より大きな問題は同期です。スレッドのワーキングメモリとメインメモリの関係を次のような状況を想像してください:

    1. 整数 i = 0

    2. スレッドは 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 のままです。でも実際は私が2歳であることを願っています

    7. 返事
      0
  • キャンセル返事