Computer >> 컴퓨터 >  >> 프로그래밍 >> Java

자바(Java) Fail-Fast와 Fail-Safe 이터레이터의 차이점 완벽 정리

자바에서 컬렉션(Collection)을 순회(iteration)하는 동안 컬렉션에 변경이 일어나면 어떻게 될까요? 자바는 이 상황을 처리하는 두 가지 방식을 제공합니다. 바로 Fail-Fast(빠른 실패)Fail-Safe(실패 없음/안전 실패)입니다.

Fail-Fast 이터레이터는 순회 중 컬렉션 구조가 수정되면 즉시 ConcurrentModificationException을 던져 문제를 알립니다. 반면 Fail-Safe 이터레이터는 원본 컬렉션이 아닌 복제본(copy)을 대상으로 동작하기 때문에 순회 중에도 수정이 가능하며 예외를 발생시키지 않습니다.

Fail-Fast와 Fail-Safe 비교표

번호구분Fail-FastFail-Safe
1예외 발생 여부스레드가 컬렉션을 순회하는 도중 추가, 삭제, 수정 등 컬렉션에 변화가 생기면 ConcurrentModificationException을 던집니다.컬렉션의 복사본을 사용하므로 예외를 발생시키지 않습니다.
2대표 컬렉션ArrayList, HashMap 등이 Fail-Fast 이터레이터의 대표적인 예입니다.CopyOnWriteArrayList, ConcurrentHashMap 등이 Fail-Safe 이터레이터의 대표적인 예입니다.
3성능과 메모리실제 컬렉션 위에서 직접 동작하므로 추가적인 메모리와 시간이 필요하지 않습니다.실제 컬렉션이 아닌 복제본 위에서 동작하므로 시간과 메모리 측면에서 오버헤드가 발생합니다.
4수정 허용 여부순회 중에는 컬렉션의 수정을 허용하지 않습니다.순회 중에도 컬렉션의 수정을 허용합니다.

Fail-Safe 예제 코드

아래 예제는 ConcurrentHashMap을 사용한 Fail-Safe 동작을 보여줍니다. 순회 도중 새로운 요소를 추가해도 예외가 발생하지 않습니다.

public class FailSafeExample {
    public static void main(String[] args) {
        ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<String, Integer>();
        // 맵에 요소 추가
        map.put("Dell", 1);
        map.put("IBM", 2);
        // 맵에서 이터레이터 가져오기
        Iterator<String> it = map.keySet().iterator();
        while (it.hasNext()) {
            String key = (String) it.next();
            System.out.println(key + " : " + map.get(key));
            map.put("Google", 3); // 순회 중 수정해도 예외 없음
        }
    }
}

실행 결과

IBM : 2
Dell : 1

Fail-Fast 예제 코드

반면 아래 예제는 ArrayList를 사용한 Fail-Fast 동작을 보여줍니다. 순회 도중 요소를 추가하려 하면 ConcurrentModificationException이 발생합니다.

public class FailFastExample {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(2);
        list.add(3);
        // 리스트에서 이터레이터 가져오기
        Iterator<Integer> it = list.iterator();
        while (it.hasNext()) {
            Integer integer = (Integer) it.next();
            list.add(4); // 순회 중 수정 → 예외 발생!
        }
    }
}

실행 결과

Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.ArrayList$Itr.checkForComodification(Unknown Source)

정리

Fail-Fast는 데이터 무결성을 빠르게 확인할 수 있어 단일 스레드 환경에서 유용하고, Fail-Safe는 멀티스레드 환경에서 안전하게 컬렉션을 다룰 수 있다는 장점이 있습니다. 다만 Fail-Safe는 복제본을 생성하는 비용이 들기 때문에 성능과 메모리 사용량을 고려하여 상황에 맞게 선택하는 것이 중요합니다.