자바에서,필요한가요 선언하는 내 컬렉션에 동기화되는 경우 그것을 읽기 전용입니까?

StackOverflow https://stackoverflow.com/questions/152342

문제

내가 채우는 컬렉션을 하나의 시간 내 J2EE 웹 애플리케이션을 시작합니다.그런 다음,여러 스레드에 액세스할 수 있습 그것은 동시에 하지만 그것을 읽는다.

내가 사용하여 알고있는 동기화된 컬렉션은 필수를 쓰지만 난 아직도 그것을 필요로를 읽습니까?

도움이 되었습니까?

해결책

이 경우 컬렉션의 내부 상태를 변경하지 않기 때문에 일반적으로 아니요. 컬렉션을 반복하면 반복자의 새 인스턴스가 생성되고 반복 상태가 반복자 인스턴스에 따라됩니다.


제쳐두 : 참고 : 읽기 전용 컬렉션을 유지하면 컬렉션 자체에 대한 수정 만 방지합니다. 각 수집 요소는 여전히 변경 가능합니다.

class Test {
    public Test(final int a, final int b) {
        this.a = a;
        this.b = b;
    }

    public int a;
    public int b;
}

public class Main {

    public static void main(String[] args) throws Exception {
        List<Test> values = new ArrayList<Test>(2);
        values.add(new Test(1, 2));
        values.add(new Test(3, 4));

        List<Test> readOnly = Collections.unmodifiableList(values);
        for (Test t : readOnly) {
            t.a = 5;
        }

        for (Test t : values) {
            System.out.println(t.a);
        }
    }

}

이 출력 :

5
5

@wmr answser의 중요한 고려 사항.

컬렉션을 읽는 스레드가 채우기 전후에 시작되었는지 여부에 따라 다릅니다. 그들이 그것을 채우기 전에 시작되면, 당신은 (동기화없이) 보증이 없으며,이 스레드는 업데이트 된 값을 볼 수 있습니다.

그 이유는 Java 메모리 모델입니다.이 링크에서 "가시성"섹션을 더 알고 싶다면 다음과 같습니다. http://gee.cs.oswego.edu/dl/cpj/jmm.html

컬렉션을 채우고 나서 스레드가 시작 되더라도 컬렉션 구현이 읽기 작업에서도 내부 상태를 변경할 수 있으므로 동기화해야 할 수도 있습니다 (감사합니다. Michael Bar-Sinai, 나는 그러한 컬렉션이 존재한다는 것을 몰랐다).

객체, 가시성 등의 출판과 같은 주제를 다루는 동시성 주제에 대한 또 다른 흥미로운 읽기는 Brian Goetz의 책입니다. 실제로 Java 동시성.

다른 팁

컬렉션을 읽는 스레드가 채우기 전후에 시작되었는지 여부에 따라 다릅니다. 그들이 그것을 채우기 전에 시작되면, 당신은 (동기화없이) 보증이 없으며,이 스레드는 업데이트 된 값을 볼 수 있습니다.

그 이유는 Java 메모리 모델입니다.이 링크에서 "가시성"섹션을 더 알고 싶다면 다음과 같습니다. http://gee.cs.oswego.edu/dl/cpj/jmm.html

컬렉션을 채우고 나서 스레드가 시작 되더라도 컬렉션 구현이 읽기 작업에서도 내부 상태를 변경할 수 있으므로 동기화해야 할 수도 있습니다 (감사합니다. Michael Bar-Sinai, 나는 그러한 컬렉션이 표준 JDK에 존재한다는 것을 몰랐다).

객체, 가시성 등의 출판과 같은 주제를 다루는 동시성 주제에 대한 또 다른 흥미로운 읽기는 Brian Goetz의 책입니다. 실제로 Java 동시성.

일반적으로, 당신은해야합니다. 일부 컬렉션은 읽기 중에 내부 구조를 변경하기 때문입니다. 액세스 오더를 사용하는 링크드 하슈 맵이 좋은 예입니다. 그러나 단지 내 말을 받아들이지 마십시오.

액세스 주문 링크 된 해시 맵에서는 Get과 함께 맵을 쿼리하는 것만으로는 구조적 수정입니다. 링크 된 해시지도의 Javadoc

캐시, 컬렉션 통계, 최적화, 전혀 재미있는 것들이 없다고 확신한다면 동기화 할 필요가 없습니다. 이 경우 컬렉션에 유형 제약 조건을 넣었을 것입니다. 컬렉션을지도 (LinkedHashMap을 허용하는)로 선언하지 말고 Hashmap (순수 주의자, Hashmap의 최종 서브 클래스)으로 선언합니다. 멀리...).

하지 않아에서 설명한 다른 답변이 있습니다.당신이 원하는지 확인하는 귀하의 컬렉션은 읽기만 사용할 수 있습니다:

yourCollection = Collections.unmodifableCollection(yourCollection);

(유사한 방법이 존재에 대한 목록에 설정,지도 및 기타 컬렉션형)

컬렉션 자체는 그렇지 않지만, 보유한 것이 불변이 아니라면, 그 별도 클래스는 자체 동기화가 필요하다는 것을 명심해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top