Java에서 ConcurrentHashMap 구현

3144 단어 JavaConcurrentHashMap
ConcurrentHashMap(약칭 CHM)은 자바 1.5에서 Hashtable의 대체 선택으로 새로 도입된 것으로 concurrent 패키지의 중요한 구성원이다.자바 1.5 이전에 다중 스레드와 병렬 프로그램에서 안전하게 사용할 수 있는 맵을 실현하려면 Hash Table과synchronized Map에서만 선택할 수 있습니다. 왜냐하면 Hash Map은 스레드가 안전하지 않기 때문입니다.하지만 CHM을 도입한 후에 우리는 더 좋은 선택을 하게 되었다.CHM은 스레드가 안전할 뿐만 아니라 HashTable과synchronizedMap보다 성능이 좋습니다.Hash Table과synchronized Map에 비해 전체 맵을 잠그고 CHM은 일부 맵만 잠그고 있습니다.CHM은 쓰기 작업을 동기화하여 데이터 무결성을 유지하는 동시에 동시 읽기 작업을 허용합니다.우리는 이미 Top 5 Java Concurrent Collections from JDK 5 and 6에서 CHM의 기초 지식을 배웠습니다. 이 블로그에서 저는 다음과 같은 몇 가지를 소개할 것입니다.
  • CHM이 Java에서 어떻게 구현되었는지
  • 어떤 상황에서 CHM을 사용해야 하는지
  • 자바에서 CHM을 사용하는 예
  • CHM의 주요 특징
  • Java에서 ConcurrentHashMap 구현
    CHM은 분할을 도입하고 HashTable에서 지원하는 모든 기능을 제공합니다.CHM에서는 맵에 대한 다중 스레드 읽기 작업을 지원하며 Blocking이 필요하지 않습니다.이는 CHM이 맵을 서로 다른 부분으로 분할하여 업데이트 작업을 수행할 때 일부분만 잠그기 때문입니다.기본 병렬 단계 (concurrency level) 에 따라 맵은 16개 부분으로 분할되고 서로 다른 자물쇠로 제어됩니다.이것은 최대 16개의 쓰기 스레드 작업 맵을 동시에 사용할 수 있다는 것을 의미한다.한 라인만 들어갈 수 있는 것에서 16개의 쓰기 라인이 동시에 들어갈 수 있는 것으로 바꾸어 보세요. (읽기 라인은 거의 제한을 받지 않습니다.) 성능의 향상은 명백히 알 수 있습니다.그러나put(),remove(),putAll(),clear() 등 일부 업데이트 작업은 작업 부분만 잠그기 때문에 검색 작업에서 최신 결과를 되돌릴 수 없습니다.
    또 다른 중요한 점은 CHM을 반복해서 훑어볼 때 키세트가 되돌아오는 iterator는 약한 일치와fail-safe로 최근의 변화를 되돌리지 않을 수도 있고 훑어보는 과정에서 이미 훑어보는 그룹의 내용이 바뀌면 Concurrent Modification Exceptoin의 이상을 던지지 않을 수도 있다는 것이다.
    CHM의 기본 병렬 레벨은 16이지만 CHM을 생성할 때 구조 함수를 통해 변경할 수 있습니다.의심할 여지없이 병렬 단계는 병렬 업데이트 작업을 실행하는 수를 대표하기 때문에 아주 적은 라인만 맵을 업데이트할 수 있다면 낮은 병렬 단계를 설정하는 것을 권장합니다.또 CHM은 ReentrantLock을 사용하여 segments에 자물쇠를 채웠다.
    Java에서 ConcurrentHashMap putifAbsent 방법의 예
    많은 경우 우리는 원소가 존재하지 않을 때 원소를 삽입하기를 희망한다. 우리는 일반적으로 아래와 같이 코드를 쓴다
    
    synchronized(map){
     if (map.get(key) == null){
      return map.put(key, value);
     } else{
      return map.get(key);
     }
    }
    
    위의 코드는 HashMap과 HashTable에서 사용하기 좋으나 CHM에서 오류가 발생할 위험이 있습니다.이것은 CHM이put 작업을 할 때 전체 맵에 자물쇠를 채우지 않았기 때문에 한 라인이put(k,v)에 있을 때, 다른 라인이get(k)을 호출하면null을 얻을 수 있습니다. 이것은 한 라인put의 값이 다른 라인put의 값에 덮어쓰게 됩니다.물론, 코드를synchronized 코드 블록에 봉인할 수 있습니다. 이렇게 하면 비록 라인은 안전하지만, 당신의 코드를 단일 라인으로 만들 수 있습니다.CHM이 제공하는putIfAbsent(key,value) 방법은 원자적으로 같은 기능을 실현하고 위의 라인 경쟁의 위험을 피한다.
    Concurrent Hash Map은 언제 사용하나요?
    CHM은 독자 수가 쓰기를 초과할 때, 쓰기의 수가 독자보다 많을 때, CHM의 성능은 Hashtable와synchronized Map보다 낮다.전체 맵이 잠겼을 때 읽기 작업은 같은 부분에 대한 쓰기 작업이 끝날 때까지 기다려야 하기 때문이다.CHM은cache에 적용되며 프로그램이 시작될 때 초기화되고 여러 개의 요청 라인에 접근할 수 있습니다.Javadoc에서 설명한 바와 같이 CHM은 HashTable의 좋은 대체이지만, CHM은 HashTable보다 동기성이 약간 약하다는 것을 기억해야 한다.
    총결산
    이제 우리는 Concurrent Hash Map이 무엇인지, 그리고 언제 Concurrent Hash Map을 사용해야 하는지 알게 되었습니다. 다음은 CHM의 몇 가지 관건을 복습해 보겠습니다.
  • CHM은 읽기와 스레드를 동시에 안전하게 업데이트할 수 있습니다
  • 쓰기 작업을 수행할 때 CHM은 맵의 일부만 잠깁니다
  • 병렬 업데이트는 내부에서 병렬 단계에 따라 맵을 작은 부분으로 분할하여 이루어진다
  • 높은 병발 등급은 시간과 공간의 낭비를 초래하고 낮은 병발 등급은 라인을 많이 쓸 때 라인 간의 경쟁을 일으킨다
  • CHM의 모든 작업은 스레드 안전입니다
  • CHM이 되돌아오는 교체기는 약한 일치성,fail-safe이며 ConcurrentModificationException 이상을 던지지 않습니다
  • CHM은 null의 키 값을 허용하지 않습니다
  • HashTable 대신 CHM을 사용할 수 있지만 CHM이 전체 맵을 잠그지 않는다는 것을 기억해야 한다.
  • 지금까지 Java에서 CHM의 구현과 사용 장면이 여러분에게 도움이 되었으면 좋겠습니다!여러분의 본 사이트에 대한 지지에 감사드립니다!

    좋은 웹페이지 즐겨찾기