ConcurrentHashMap 의 lock 거는 기법

일단 ConcurrentHashMap 과 HashMap 의 차이점은 다 알고 있다는 전제하에 포스팅을 작성 한다.

이 포스팅을 하게된 이유는 사실 어떤분이 나에게 ConcurrentHashMap 과 HashMap 의 차이점을 아냐고 물어봤고
물론 알고 있어서 쏼라쏼라 대답을 했지만 (Multi-Threaded 환경에서 thread safe 여부) 거기에서 끝나지 않고
또 물어보시더라 ConcurrentHashMap 이 왜 Thread 에 safe 한지? 어떤 원리인지 아세요?

그래서 나는 사실 정확하게 알진 못했지만 대략 MySQL 의 innodb 처럼 row-level lock 걸듯이 접근하고 있는 해당 Key 값에
lock을 걸지 않을까요? 라고 대답을 했다.

이 대답은 후에 찾아 보니 반은 맞고 반은 틀리더라…

그리고 다시한번 정확하게 정리한다..

——————————————————————————————————

보통은 우리가 Multi-threaded 환경에서 key-value 저장소가 필요할때 자바에서 사용하는 것이

크게

1. HashTable
2. HashMap
3. ConcurrentHashMap

이렇게 있는데 파악을 하기 위해서 각 자바 source 를 까보았다.
가장 중요한 Get, Set 부분만 보면

1. HashTable


public synchronized V More ...get(Object key)
public synchronized V More ...put(K key, V value)

보이는가? 메소드 레벨에서 synchronized 를 걸어 버린다.

2. HashMap

얘는 볼것도 없이 synchronized 가 없다. 따라서 속도는 빠르지만 Multi-threaded 환경에서 그냥 쓰면 여러 Thread 에서 동시 접근시 Exception 이 난다.

3. ConcurrentHashMap

얘는 특이하게 synchronized 가 아니라 lock 을 사용한다.


V More ...put(K key, int hash, V value, boolean onlyIfAbsent) {
lock();
try {
int c = count;
if (c++ > threshold) // ensure capacity
rehash();
HashEntry[] tab = table;
.
.
.

처음에 이 부분만 보고 아싸 내 말이 맞았구나 했다. 하지만 찾아 보니

비슷은한데 CurrentHashMap 은 Map 자체를 Currency 레벨로 영역을 쪼개서 (기본이 16개)
해당 영역별로 lock을 거는 것이었다. 이 Lock 이름은 ReentrantLock 이라고 한다.

소스에서

CurrentHashMap 생성자중에


public More ...ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel) {
...
}

이런놈이 있더라… 하아…

역시 갈길이 멀다.. 그래도 좋은거 하나 확실하게 배웠다.

댓글 남기기

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다