대부분의 클래스 Collection
에서는를 Collection
사용하여 반복 하는 동안 시간을 수정 하는 Iterator
것은 허용되지 않습니다Collection
. Java 라이브러리 Collection
는 "동시 수정"을 반복 하는 동안 수정을 시도합니다 . 불행히도 가능한 유일한 원인은 여러 스레드가 동시에 수정하는 것이지만 그렇지는 않습니다. 하나의 스레드 만 Collection
사용하여 Collection.iterator()
(또는 Enhanced for
루프를 사용하여) 반복자를 작성하고 , 반복을 시작하거나 ( Iterator.next()
Enhanced for
루프 의 본문을 사용 하거나 이와 동등하게 입력 )을 수정 한 Collection
다음 반복을 계속할 수 있습니다.
도움 프로그래머, 일부 사람들의 구현 Collection
클래스 를 시도 잘못된 동시 변경을 감지하고, 던져 ConcurrentModificationException
그들이 그것을 감지합니다. 그러나, 모든 동시 수정의 검출을 보장하는 것은 일반적으로 불가능하고 실용적이지 않다. 따라서 잘못 사용하여 Collection
항상 발생 하는 것은 아닙니다 ConcurrentModificationException
.
의 문서는 ConcurrentModificationException
말합니다 :
이 예외는 그러한 수정이 허용되지 않을 때 객체의 동시 수정을 감지 한 메소드에 의해 발생할 수 있습니다 ...
이 예외가 항상 다른 스레드에 의해 객체가 수정되었음을 나타내는 것은 아닙니다. 단일 스레드가 객체의 계약을 위반하는 일련의 메소드 호출을 발행하면 객체에서이 예외가 발생할 수 있습니다.
일반적으로 말해서 비동기식 동시 수정이있을 경우 확실한 보장을 할 수 없으므로 페일-패스트 동작을 보장 할 수 없습니다. 빠른 작업 ConcurrentModificationException
은 최선의 노력으로 이루어집니다.
참고
- 예외 는 던져 질 수 있으며 던져 질 필요 는 없다
- 다른 스레드가 필요하지 않습니다
- 예외를 던지는 것은 보장 할 수 없습니다
- 예외를 던지는 것은 최선의 노력으로 이루어집니다
- 동시 수정이 감지 될 때가 아니라 예외가 발생 하면 예외 가 발생합니다.
의 문서 HashSet
, HashMap
, TreeSet
과 ArrayList
수업이 말한다 :
[이 클래스에서 직접 또는 간접적으로] 리턴 된 반복자는 실패가 빠릅니다. 반복자의 고유 한 remove 메소드를 제외하고 어떤 식 으로든 반복자가 작성된 후 [컬렉션]이 수정되면 Iterator
throw는 ConcurrentModificationException
. 따라서 동시 수정에 직면하여 반복자는 미래에 결정되지 않은 시간에 임의의 비 결정적 동작을 위험에 빠뜨리기보다는 신속하고 깨끗하게 실패합니다.
일반적으로 말하자면, 비 동기화 된 동시 수정이있을 경우 어떠한 엄격한 보장도 불가능하므로 반복자의 페일-패스트 동작을 보장 할 수 없습니다. 빠른 속도의 이터레이터 ConcurrentModificationException
는 최선의 노력으로 던집니다 . 따라서이 예외에 따라 프로그램이 정확 하지 않은 경우 작성하는 것이 잘못 될 수 있습니다. 이터레이터의 빠른 동작은 버그를 탐지하는 데만 사용해야합니다 .
이 동작은 "보장 할 수 없으며"최선의 노력으로 만 이루어집니다.
Map
인터페이스 의 여러 방법에 대한 문서는 다음과 같이 말합니다.
비 동시 구현은이 메소드를 대체해야하며 최선의 노력으로 ConcurrentModificationException
맵핑 함수가 계산 중에이 맵을 수정하는 것이 감지되면 if를 처리하십시오. 동시 구현은이 메소드를 대체해야하며 최선의 노력으로 IllegalStateException
맵핑 함수가 계산 중에이 맵을 수정하고 결과적으로 계산이 완료되지 않는 것으로 감지되면 if를 처리하십시오.
검색에는 "최선의 노력" ConcurrentModificationException
만 필요하며, 비 동시 (스레드에 안전하지 않은) 클래스에만 명시 적으로 제안됩니다.
디버깅 ConcurrentModificationException
따라서로 인해 스택 추적 ConcurrentModificationException
이 표시되면 원인이 안전하지 않은 멀티 스레드 액세스라고 가정 할 수 없습니다 Collection
. 당신은해야한다 스택 추적을 검토 중 어떤 클래스를 결정하기 위해 Collection
예외 던졌다 (클래스의 방법은 직접 또는 간접적으로 발생해야합니다), 그리고있는 Collection
객체입니다. 그런 다음 해당 오브젝트를 수정할 수있는 위치에서 검사해야합니다.
- 가장 일반적인 원인은에
Collection
대한 향상된 for
루프 내의 수정입니다 Collection
. 당신이 보이지 않는해서 Iterator
의미하지 않는다 소스 코드에서 객체를 더 없다 Iterator
거기! 다행히도 잘못된 for
루프 의 문 중 하나 가 일반적으로 스택 추적에 있으므로 오류를 쉽게 추적 할 수 있습니다.
- 까다로운 경우는 코드가
Collection
객체에 대한 참조를 전달할 때 입니다. 참고 불가능한 (제조와 같은 모음 뷰 Collections.unmodifiableList()
정도)의 수정 컬렉션에 대한 참조를 유지하기 에 "불가능한"컬렉션 예외를 발생시킬 수 이상 반복 (변형 예는 다른 곳에서 수행되었다). 하위 목록 , 항목 세트 및 키 세트 와 같은 의 다른 보기 도 원본 (수정 가능)에 대한 참조를 유지 합니다. 이것은 심지어 스레드 안전에 대한 문제가 될 수 있습니다 와 같은, ; 스레드 안전 (동시) 컬렉션이 예외를 throw 할 수 없다고 가정하지 마십시오.Collection
Map
Map
Collection
Collection
CopyOnWriteList
- 경우에 따라 어떤 작업을 수정하여
Collection
예기치 않은 결과가 발생할 수 있습니다. 예를 들어 LinkedHashMap.get()
컬렉션을 수정합니다 .
- 가장 어려운 경우는 예외 가 여러 스레드에 의한 동시 수정으로 인한 경우 입니다 .
동시 수정 오류를 방지하기위한 프로그래밍
가능하면 Collection
객체에 대한 모든 참조를 제한 하므로 동시 수정을 쉽게 방지 할 수 있습니다. 만들기 기능 객체 또는 로컬 변수 및 참조를 반환하지 않는 방법 또는 그 반복자. 그러면 수정 가능한 모든 장소 를 검사 하는 것이 훨씬 쉽습니다 . (가) 경우 여러 스레드에 의해 사용되는, 스레드가 액세스 할 수 있도록 다음 실용적인 적절한 개시 또는 종료 이벤트들이 발생하고 잠금 만.Collection
private
Collection
Collection
Collection
Collection