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

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의 각 스레드에는 자체 작업 메모리가 있으며 이는 주 메모리의 복사본으로 이해될 수 있습니다. 휘발성을 사용하는 경우 주 메모리에서 즉시 읽을 수 있다는 것만 보장할 수 있으며 각 스레드의 작업 메모리와의 원자적 동기화를 보장할 수 없습니다.

휘발성을 사용하지 않고 쓰기 작업에만 동기화를 추가하고 읽기 작업에는 추가하지 않더라도 최신 값을 읽을 수 없다는 문제뿐만 아니라 더 큰 문제는 동기화입니다. 스레드 작업 메모리와 주 메모리의 다음 상황을 상상해 보세요.

  1. 정수 i = 0

  2. 스레드는 i + 1을 제공합니다

  3. a가 이 +1 작업을 수행하는 동안 스레드 b는 i를 자체 작업 메모리로 읽어 들입니다. 이때 읽기가 잠겨 있지 않기 때문에 i는 여전히 0입니다.

  4. 스레드 실행 완료, i = 1, 그리고 메인 메모리에 동기화

  5. b는 i에 대해 +1 작업을 수행합니다. a가 쓰기 잠금을 해제했으므로 b는 쓸 수 있지만 자체 작업 메모리의 i는 0이므로 +1 이후에도 여전히 1입니다.

  6. b 작업이 완료되어 주 메모리에 동기화됩니다. 주 메모리의 i는 여전히 1입니다. 하지만 사실 난 2살이었으면 좋겠다

최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿