0.들어가기전
- ArrayList와 HashMap을 Thread safe하게 사용 하는 방법은 무엇인가?에 대한 대답으로 아래의 내용을 공부 해 보았다
1.Thread Safe 란?
- 멀티 쓰레드 환경에서 개발자가 의도한대로 코드가 동작하는 것
- 어떤 함수나 변수, 객체가 여러 스레드에서 동시에 접근이 이루어져도 수행 결과가 의도 한대로 나오는 것.
2.HashMap을 Thread Safe 하게 사용하는 방법
ConcurrentHashMap
- 스레드가 안전한 연산을 할 수 있게 해주는 해시맵
- ConcurrentHashMap은 multi-threaded 환경에서 안정적으로 동작하고 HashTable과 synchronized map 보다 더 나은 성능을 가지고 있다. 그 이유는, ConcurrentHashMap은 map의 일부에만 lock을 거는데 반해, 앞의 두 가지는 map 전체에 lock을 걸기 때문이다.
- 읽기가 쓰기보다 많을 때 가장 적합하다. 만약 쓰기가 더 많거나 쓰기가 읽기와 비슷하다면 ConcurrentHashMap의 성능은 synchronizedmap 또는 HashTable 만큼 떨어지게 된다. ConcurrentHashMap은 어플리케이션의 구동 후에 많은 요청을 처리하는 쓰레드에서 엑세스 하는 동안 초기화할 수 있기 때문에 cache 용도로 아주 적합하다. ConcurrentHashMap은 또한 HashTable의 좋은 대체안이기도 하며 가능한한 ConcurrentHashMap을 사용하라고 javadoc에 기술되어 있다. 다만 ConcurrentHashMap이 동기화 부분에는 HashTable 보다 조금 단점을 가지고 있다고 보면 되겠다.
3.ArrayList를 Thread Safe 하게 사용하는 방법
CopyOnWriteArrayList
- 자바 1.5부터 사용 가능
- 내부를 변경하는 작업은 항상 깨끗한 복사본을 만들어서 수행하도록 구현되어 있다. 내부의 배열은 절대 변경할 수 없으므로 순회할 때 락이 필요 없어서 속도면에서 매우 빠르다는 장점이 있다.
- 데이터 수정이나 삭제 등의 다른 용도로 쓰일 경우에는 속도가 느려지기 때문에 수정할 일은 거의 없으며 주로 순회가 일어나는 용도로 사용하는 것이 적합하다.
- 모든 쓰기 동작(add, set, remove, etc)시, 원본배열에 있는 요소를 복사(Copy)하여 새로운 임시배열을 만들고 이 임시배열에 쓰기 동작을 수행 후 원본배열을 갱신한다. 이 덕분에 읽기(get, etc) 동작은 lock에서 자유로울 수 있게 되고, 이는 읽기 Performance에서 CopyOnWriteArrayList가 SynchronizedList보다 우월한 강력한 이유다.
SynchronizedList
- 자바 1.2버전 부터 존재.
- SyncronizedList의 모든 읽기와 쓰기 동작은 이름에 걸맞게 ’synchronized’ 키워드로 동기화 되어 있는데, 이는 하나의 스레드만이 해당 리스트에 대해 읽기나 쓰기를 할 수 있다는 것
- CopyOnWriteArrayList는 SynchronizedList보다 쓰기 동작이 느리다. 이미 이야기 했지만 CopyOnWriteArrayList은 비용이 상대적으로 높은 배열 복사 작업을 하기 때문이다.
결론
- SynchronizedList는 단순히 'synchronized' 키워드를 사용한 동기화된 List이다. 따라서 모든 읽기, 쓰기 동작에 lock이 작용된다. 반복 작업 또한 동기화 블록 안에서 수행 된다. 때문에 읽기보다 쓰기 동작이 많고, 크기가 큰 리스트의 경우에 적합할 것이다.
- 반면에 CopyOnWriteArrayList는 특유의 동작 방식으로 인해 반복작업(iterating)과 같은 읽기 동작의 Performance가 좋다. 다만 또 그 특유의 동작 방식으로 인해 쓰기 동작에서 상당한 Overhead가 발생한다. 따라서 쓰기보다 읽기 동작이 많고, 크기가 작은 리스트에 적용하는 것이 바람직하다.
Uploaded by Notion2Tistory v1.1.0