자바5 이전엔, 동기화된 컬렉션 클래스는 내부 변수에 접근하는 경로를 일련화해 스레드 안전성을 확보했다. 하지만 이 경우 동시 사용성에서 큰 손해를 볼 수 밖에 없었다. 자바 5 에서 등장한 병렬 컬렉션은 여러 스레드에서 동시에 사용될 수 있도록 설계되었다.
ConcurrentHashMap
기존에 동기화된 컬렉션 클래스는 연산을 수행하는 시간동안 항상 락을 가지고 있어야했다. 그러나, 이경우 `HashMap.get` 또는 `List.contains`와 같은 일부 연산은 최악의 경우 모든 객체를 대상으로 메서드를 호출해야할 수도 있고 그 과정에선 다른 스레드는 내부의 값을 접근할 수 없었다.
ConcurrentHashMap은 해시를 기반으로 하는 Map으로 lock Striping이라는 세밀한 동기화 기법으로 여러 스레드에서 공유하는 상태에 대응할 수 있었다. 병렬성과 확장성을 개선한 것이다.
Read는 여러 스레드에서 동시에 처리할 수 있고, Read and Write도 동시에 처리할 수 있다. Write도 제한된 개수만큼은 동시에 사용할 수 있게 동시성을 확보했다.
또한, 멀티스레드에서 병렬성을 확보했다해서 단일 스레드에서의 성능저하가 존재하지 않는다.
Lock Striping이란?
모든 버킷에 대한 락을 설정하는 것이 아닌, 접근하는 버킷에 대해서만 락을 거는 기법. 1,3,5번 버킷이 사용중이면 2,4번 버킷에 대해서는 접근이 가능하다는 것이다.
또한 Iterator를 사용할때 ConcurrentModificationException이 발생하지 않는다.
Iterator는 즉시 멈춤 전략이 아닌, 미약한 일관성 전략을 사용한다. 이를 통해 반복문과 동시에 컬렉션의 내용을 변경해도 Iterator를 생성한 시점의 값으로 반복을 계속할 수 있다.
(또한 보장할 순 없지만 이후의 변경된 내용을 반영해 동작할 수도 있다고한다.)
한계?
그러나, 조금 더 신경써야할 부분도 존재한다. 병렬성 문제로 인해 Map을 상속받은 클래스의 공통 메서드인 size, isEmpty 메서드를 사용하기 어려워졌다. 병렬성으로 인해 실제 리턴하는 시점에 값이 바뀌었을 수도 있기 때문에 해당 메서드의 반환값은 실제 값이라기보단 추정값이다.
또한, 맵을 독점적으로 사용할 수 있도록 막아버리는 기능은 지원하지 않는다.
HashTable, SynchronizedMap에서는 독점적으로 락을 잡아 다른 스레드에서 사용할 수 없게하지만, ConcurrentHashMap에선 그런 기능을 제공하지 않는다.
따라서, 독점적으로 자원을 사용해야하는 경우가 있다면 좋은 선택은 아니다.
없을 경우에만 추가하는 상황을 보자.
ConcurrentHashMap은 독점적으로 사용할 수 있는 락이 없기에 어려움을 겪을 수 있다. 하지만, 이경우에 이미 구현된 putIfAbsent, removeIf 등이 이미 구현되어있다.
CopyOnWriteArrayList
ArrayList를 상속받은 CopyOnWriteArrayList는 `변경할때마다 복사`하는 컬렉션 클래스로 불변 객체를 외부에 공개할때 멀티스레드 환경에서 별도의 동기화 작업이 필요없다는 원리를 바탕으로 스레드 안전성을 확보한다.
컬렉션의 변경은 불가피하다. 따라서, 내용이 변경될때마다 새로운 복사본을 생성하고 작업하기에, 원본이 변할일이 없어 스레드 안전성을 확보하는 것이다.
만약, CopyOnWriteArrayList에서 Iterator를 사용한다면, 사용 시점의 복사본(A)을 기준으로 전달되어 작업하며, 반복하는 동안 컬렉션에 추가, 삭제등의 내용이 있을시에는 Iterator에서 참조하지 않는 다른 복사본(B)에 반영되기에 동시 사용 문제가 없다.
물론 단점도 있다. 데이터가 변경될때마다 새로운 복사본을 만들기에, 성능 손해를 볼 수 있고, 특히 컬렉션의 양이 크다면 더욱 그렇다. 따라서, 변경 작업보다는 반복문으로 읽어내는 작업이 더 빈번한 경우 더욱 효과적이다.
'PL > 모던 자바 인 액션' 카테고리의 다른 글
모던 자바 인 액션 - Chap12 (0) | 2023.10.09 |
---|---|
모던 자바 인 액션 - Chap11 (0) | 2023.10.09 |
모던 자바 인 액션 7주차 - Chap 08 (0) | 2023.09.30 |
모던 자바 인 액션 6주차 - Chap07 (0) | 2023.09.21 |
자바 병렬 프로그래밍 - 3장 (0) | 2023.09.21 |