오류의 원인 checkForComodification() 은 보고된 오류에서 알 수 있습니다. 오류를 방지하려면 modCount != expectedModCount 을 false 로 유지해야 합니다. list.remove(Object)에서는 fastRemove(int) 메소드를 호출하게 되는데, 이때 불가피하게 modCount을 수정하게 되는데 이때 오류가 발생하게 됩니다. Iterator<String> iterator = list.iterator() ; 이 메소드의 구현은 내부 클래스 Itr(이 클래스는 반복 프로세스에서 사용됨)를 반환하는 것이지만, 이 iterator.remove()가 오류를 일으키지 않는 이유는 이 메소드 간의 관계 때문입니다. 그리고 실제 ArrayList.this.remove을 하기 전에 checkForComodfication를 확인하고 remove 뒤에 expectedModCount = modCount을 만들어서 오류가 발생하지 않도록 구현하는 것입니다.
싱글 쓰레드의 경우 List 순회 시 요소 삭제 시 List의 Remove 메소드 대신 Iterator의 Remove 메소드를 사용해야 하며, 그렇지 않으면 ConcurrentModificationException이 발생합니다. 선생님이 학급 전체의 학생 수를 세고 있는데, 학생들이 규칙을 따르지 않고 나가고 들어오면 선생님은 확실히 그 숫자를 셀 수 없을 것이라고 상상해 보세요.
멀티스레딩의 경우 제 블로그 중 하나를 참고해주세요: http://xxgblog.com/2016/04/02...
우선 여기에는 다중 스레드 작업이 포함됩니다. Iterator는 다중 스레드 작업을 지원하지 않습니다. List 클래스는 수정 횟수를 기록하기 위해 내부적으로 modCount 변수를 유지합니다. 예: ArrayList 소스 코드
으아아아
Iterator가 생성될 때마다 Iterator는 modCount를 기록합니다. next() 메서드가 호출될 때마다 레코드는 외부 클래스 List의 modCount와 비교됩니다. 다중 스레드 편집 예외가 발생합니다.
왜 이러는 걸까요? 내가 이해한 바에 따르면, 탐색할 컬렉션의 콘텐츠와 밀접하게 결합된 반복자를 생성했는데, 이는 이 반복기에 해당하는 컬렉션의 콘텐츠가 현재 콘텐츠라는 것을 의미합니다. 버블 정렬이 실행될 때 여전히 내 컬렉션에 데이터를 삽입하는 스레드가 있습니다. 그렇죠? 따라서 Java는 순회 중에 컬렉션이 수정되는 것을 방지하기 위해 이 간단한 처리 메커니즘을 사용합니다.
"1"을 삭제해도 괜찮은 이유는 foreach 및 iterator의 hasNext() 메서드에 있습니다. 실제로 foreach의 구문 설탕은
입니다.
으아아아
따라서 모든 루프는 hasNext()를 먼저 실행하므로 ArrayList의 hasNext()가 어떻게 작성되는지 살펴보세요.
으아아아
cursor는 반복자의 위치를 표시하는 데 사용되는 변수입니다. 변수는 0부터 시작하여 next가 호출될 때마다 +1 연산을 수행합니다. 코드가 "1"을 삭제한 후 size=1, 커서 =1, 이때 hasNext()는 false를 반환하고 루프를 종료하므로 반복자가 두 번째 요소를 찾기 위해 next를 호출하지 않으므로 modCount를 감지할 방법이 없으므로 멀티 스레드 수정 예외가 발생하지 않습니다. 🎜> 그런데 "2"를 삭제하면 iterator가 next를 두 번 호출했는데 이때 size=1,cursor=2, hasNext()가 true를 반환했기 때문에 Iterator는 어리석게도 next()를 다시 호출하여 If도 발생했습니다. modCount가 동일하지 않으면 다중 스레드 수정 예외가 발생합니다.
세트에 세 개의 요소가 있는 경우 "1"을 삭제하면 예외가 발생하지만 "2"를 삭제하면 문제가 발생하지 않는 이유는 위 프로그램의 실행과 관련이 있습니다. 순서는 일관됩니다.
오류의 원인
checkForComodification()
은 보고된 오류에서 알 수 있습니다. 오류를 방지하려면modCount != expectedModCount
을false
로 유지해야 합니다.list.remove(Object)
에서는fastRemove(int)
메소드를 호출하게 되는데, 이때 불가피하게modCount
을 수정하게 되는데 이때 오류가 발생하게 됩니다.Iterator<String> iterator = list.iterator()
; 이 메소드의 구현은 내부 클래스Itr
(이 클래스는 반복 프로세스에서 사용됨)를 반환하는 것이지만, 이iterator.remove()
가 오류를 일으키지 않는 이유는 이 메소드 간의 관계 때문입니다. 그리고 실제ArrayList.this.remove
을 하기 전에checkForComodfication
를 확인하고remove
뒤에expectedModCount = modCount
을 만들어서 오류가 발생하지 않도록 구현하는 것입니다.
으아아아Itr.remove
구현잘못된 점이 있으면 지적해주세요 @ChaCha哥 @puliuyinyi
싱글 쓰레드의 경우 List 순회 시 요소 삭제 시 List의 Remove 메소드 대신 Iterator의 Remove 메소드를 사용해야 하며, 그렇지 않으면 ConcurrentModificationException이 발생합니다. 선생님이 학급 전체의 학생 수를 세고 있는데, 학생들이 규칙을 따르지 않고 나가고 들어오면 선생님은 확실히 그 숫자를 셀 수 없을 것이라고 상상해 보세요.
멀티스레딩의 경우 제 블로그 중 하나를 참고해주세요: http://xxgblog.com/2016/04/02...
우선 여기에는 다중 스레드 작업이 포함됩니다. Iterator는 다중 스레드 작업을 지원하지 않습니다. List 클래스는 수정 횟수를 기록하기 위해 내부적으로 modCount 변수를 유지합니다.
으아아아예: ArrayList 소스 코드
Iterator가 생성될 때마다 Iterator는 modCount를 기록합니다. next() 메서드가 호출될 때마다 레코드는 외부 클래스 List의 modCount와 비교됩니다. 다중 스레드 편집 예외가 발생합니다.
왜 이러는 걸까요? 내가 이해한 바에 따르면, 탐색할 컬렉션의 콘텐츠와 밀접하게 결합된 반복자를 생성했는데, 이는 이 반복기에 해당하는 컬렉션의 콘텐츠가 현재 콘텐츠라는 것을 의미합니다. 버블 정렬이 실행될 때 여전히 내 컬렉션에 데이터를 삽입하는 스레드가 있습니다. 그렇죠? 따라서 Java는 순회 중에 컬렉션이 수정되는 것을 방지하기 위해 이 간단한 처리 메커니즘을 사용합니다.
"1"을 삭제해도 괜찮은 이유는 foreach 및 iterator의 hasNext() 메서드에 있습니다. 실제로 foreach의 구문 설탕은
입니다. 으아아아따라서 모든 루프는 hasNext()를 먼저 실행하므로 ArrayList의 hasNext()가 어떻게 작성되는지 살펴보세요.
으아아아cursor는 반복자의 위치를 표시하는 데 사용되는 변수입니다. 변수는 0부터 시작하여 next가 호출될 때마다 +1 연산을 수행합니다.
세트에 세 개의 요소가 있는 경우 "1"을 삭제하면 예외가 발생하지만 "2"를 삭제하면 문제가 발생하지 않는 이유는 위 프로그램의 실행과 관련이 있습니다. 순서는 일관됩니다.코드가 "1"을 삭제한 후 size=1, 커서 =1, 이때 hasNext()는 false를 반환하고 루프를 종료하므로 반복자가 두 번째 요소를 찾기 위해 next를 호출하지 않으므로 modCount를 감지할 방법이 없으므로 멀티 스레드 수정 예외가 발생하지 않습니다. 🎜> 그런데 "2"를 삭제하면 iterator가 next를 두 번 호출했는데 이때 size=1,cursor=2, hasNext()가 true를 반환했기 때문에 Iterator는 어리석게도 next()를 다시 호출하여 If도 발생했습니다. modCount가 동일하지 않으면 다중 스레드 수정 예외가 발생합니다.
요소를 추가하거나 삭제하면 컬렉션의 번호가 변경되므로 순회 시 문제가 발생할 수 있습니다. 예를 들어 컬렉션에 요소가 10개 있으면 요소를 추가하거나 삭제할 경우 10번 순회해야 합니다. 순회 횟수가 정확하지 않아 오류가 보고됩니다
역순으로 삭제하세요. 어쨌든 목록을 삭제하지 마세요. 삭제 태그를 추가할 수 있습니다
문서에 있는 노란색 설명이 매우 흥미롭습니다.
이에 대해서는
ArrayList
의 소스코드를 살펴봐야 한눈에 알 수 있습니다.역순으로 삭제하면 됩니다
ArrayList는 스레드로부터 안전하지 않습니다. 즉, 순회하는 동안 목록을 수정한다는 의미입니다.
이 경우 ArrayList는 동시 수정 예외를 발생시킵니다.