찾다

 >  Q&A  >  본문

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일 전669

모든 응답(1)나는 대답할 것이다

  • PHP中文网

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

    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살이었으면 좋겠다

    회신하다
    0
  • 취소회신하다