[Java] HashMap 에서 ConcurrentModificationException 발생

프로그래밍/자바2020. 2. 10. 11:55

아주 간헐적으로 발생하는 이슈가 발견됐습니다.

HashMap에서.. ConcurrentModificationException이 발생됐습니다.

 

java.util.ConcurrentModificationException:

at java.util.HashMap$HashIterator.nextNode (HashMap.java:1441)

at java.util.HashMap$EntryIterator.next (HashMap.java:1475)

at java.util.HashMap$EntryIterator.next (HashMap.java:1473)

at java.util.AbstractMap.toString (AbstractMap.java:554)

at java.lang.String.valueOf (String.java:2896)

at java.lang.StringBuilder.append (StringBuilder.java:132)

at com.xxx.yyy.FragmentA$4.onResponse (FragmentA.java:306)

at okhttp3.RealCall$AsyncCall.run (RealCall.kt:140)

at java.util.concurrent.ThreadPoolExecutor.runWorker (ThreadPoolExecutor.java:1167)

at java.util.concurrent.ThreadPoolExecutor$Worker.run (ThreadPoolExecutor.java:641)

at java.lang.Thread.run (Thread.java:764)

 

concurrent는 '동시에' 라는 뜻을 가지고 있습니다. 그래서 ConcurrentModificationException은.. 한글로 번역하면 동시수정에러 정도가 될 것 같네요.

 

ConcurrentModificationException이 발생하는 경우는 2가지가 있다고 합니다.

1. 서로 다른 Thread가 동시에 같은 HashMap에 연산을 수행 함

2. for문 안에서 HashMap의 entry를 제거함

 

HashMap.java코드를 봤습니다.

        final Node<K,V> nextNode() {
            Node<K,V>[] t;
            Node<K,V> e = next;
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
            if (e == null)
                throw new NoSuchElementException();
            if ((next = (current = e).next) == null && (t = table) != null) {
                do {} while (index < t.length && (next = t[index++]) == null);
            }
            return e;
        }

Exception이 발생한 위치를 보니.. modCount != expectedModCount에서 걸려서 예외가 발생했습니다.

 

음.. 대충보니 for문으로 HashMap을 돌고 있는데 내부 entry가 수정되서 예외가 발생한 것 같습니다.

그런데 신기한 것은.. 그냥 로그로 Log.d("TAG", "hashMap = " + hashMap); 과 같이 그냥 로그 찍는 부분에서 이 예외가 발생했네요. 

 

hashMap.toString()에서.. 혼자 예외가 발생하진 않았을 것 같고.. 아마 다른 Thread에서 이 hashMap에 접근해서 데이터를 조작하다가.. 문제가 생긴 것 같습니다.

 

그래서 그냥.. HashMap을 ConcurrentHashMap으로 바꿔서 사용하려고 합니다.. ㅎㅎ

 

ConcurrentHashMap<String, String> myHashMap = new ConcurrentHashMap<>();

위와 같은 식으로.. 객체 타입만 HashMap이던 것을 ConcurrentHashMap으로 변경하면 됩니다.

ConcurrentHashMap은 동기화되면서 작업되므로.. 그냥 HashMap보다는 더 느리다고 하는데 뭐.. 체감이 될까 싶네요.

 

어쨋든 이렇게 수정하고 경과를 보겠습니다.

 

참고

https://www.benchresources.net/map-how-concurrentmodificationexception-can-be-handled-in-java/

작성자

Posted by 드리머즈

관련 글

댓글 영역