[java] ConcurrentHashMap과 Collections.synchronizedMap (Map)의 차이점은 무엇입니까?

여러 스레드에서 동시에 수정해야 할 맵이 있습니다.

Java API에는 세 가지 동기화 된 Map 구현이있는 것 같습니다.

  • Hashtable
  • Collections.synchronizedMap(Map)
  • ConcurrentHashMap

내가 이해 한 바에 Hashtable따르면, 구식 구현 (더 이상 사용되지 않는 Dictionary클래스 확장 )은 나중에 Map인터페이스 에 맞게 조정되었습니다 . 이 동안 되어 동기화가 심각한 것 같다 확장 성 문제를 새로운 프로젝트에 좋습니다.

그러나 다른 두 사람은 어떻습니까? 에 의해 반환 된지 Collections.synchronizedMap(Map)도와 ConcurrentHashMaps 의 차이점은 무엇입니까 ? 어느 상황에 맞는가?



답변

필요에 따라을 사용하십시오 ConcurrentHashMap. 여러 스레드에서 맵을 동시에 차단하지 않고도 수정할 수 있습니다. Collections.synchronizedMap(map)일관성을 보장하지만 (올바르게 사용되는 경우) 성능을 저하시키는 차단 맵을 만듭니다.

데이터 일관성을 보장해야하고 각 스레드에 최신 맵보기가 필요한 경우 두 번째 옵션을 사용하십시오. 성능이 중요한 경우 첫 번째를 사용하고 각 스레드는 읽기 빈도가 낮은 데이터 만 맵에 삽입합니다.


답변

╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║   Property    ║     HashMap       ║    Hashtable      ║  ConcurrentHashMap  ║
╠═══════════════╬═══════════════════╬═══════════════════╩═════════════════════╣
║      Null     ║     allowed       ║              not allowed                ║
║  values/keys  ║                   ║                                         ║
╠═══════════════╬═══════════════════╬═════════════════════════════════════════╣
║ Thread-safety ║                   ║                                         ║
║   features    ║       no          ║                  yes                    ║
╠═══════════════╬═══════════════════╬═══════════════════╦═════════════════════╣
║     Lock      ║       not         ║ locks the whole   ║ locks the portion   ║
║  mechanism    ║    applicable     ║       map         ║                     ║
╠═══════════════╬═══════════════════╩═══════════════════╬═════════════════════╣
║   Iterator    ║               fail-fast               ║ weakly consistent   ║
╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝

록킹기구에 대해서하기 :
Hashtable 오브젝트를 잠그는 동안, ConcurrentHashMap잠금 단 버킷 .


답변

“확장 성 문제” Hashtable는 정확히 같은 방식으로 존재 Collections.synchronizedMap(Map)합니다. 매우 간단한 동기화를 사용하므로 한 스레드 만 동시에 맵에 액세스 할 수 있습니다.

간단한 삽입 및 조회가있는 경우 (매우 집중적으로 수행하지 않는 한) 큰 문제가되지 않지만 전체지도를 반복해야하는 경우 큰 문제가됩니다. 큰지도의 경우 시간이 오래 걸릴 수 있습니다. 하나의 스레드가이를 수행하고 다른 스레드는 아무것도 삽입하거나 조회하려는 경우 기다려야합니다.

ConcurrentHashMap매우 정교한 기술을 사용 동기화의 필요성을 절감하고 동기화없이 다중 스레드에 의해 병렬 읽기 액세스를 허용하고, 더 중요한 것은, 제공하는 Iterator더 동기화를 필요로하지 않으며 그것은 더 보장 여부를하게하지만 심지어지도 (interation 동안 수정 할 수 있는지 반복 중에 삽입 된 요소는 리턴되지 않습니다).


답변

ConcurrentHashMap은 Java 5 이상이 필요하지만 사용할 수있을 때 선호됩니다.

여러 스레드에서 사용될 때 잘 확장되도록 설계되었습니다. 한 번에 하나의 스레드 만 맵에 액세스하면 성능이 약간 떨어질 수 있지만 여러 스레드가 동시에 맵에 액세스하면 성능이 크게 향상 될 수 있습니다.

훌륭한 책 Java Concurrency In Practice 에서 테이블을 재현 하는 블로그 항목 을 찾았습니다 .

Collections.synchronizedMap은 다른 특성 (예 : TreeMap과 같은 정렬 된 맵)으로 맵을 마무리해야하는 경우에만 의미가 있습니다.


답변

이 두 가지의 주요 차이점 ConcurrentHashMap은 업데이트되는 데이터의 일부만 잠그고 다른 스레드는 다른 데이터 부분에 액세스 할 수 있다는 것입니다. 그러나 Collections.synchronizedMap()업데이트하는 동안 모든 데이터를 잠그고 다른 스레드는 잠금이 해제 된 경우에만 데이터에 액세스 할 수 있습니다. 많은 업데이트 작업과 상대적으로 적은 양의 읽기 작업이있는 경우을 선택해야합니다 ConcurrentHashMap.

또 다른 차이점은 ConcurrentHashMap전달 된 Map의 요소 순서를 유지하지 않는다는 것입니다. HashMap데이터를 저장할 때 와 유사합니다 . 요소 순서가 유지된다는 보장은 없습니다. 반면 Collections.synchronizedMap()전달 된 맵의 요소 순서는 유지합니다. 예를 들어, TreeMapto 를 전달하면 ConcurrentHashMap의 요소 순서는의 순서 ConcurrentHashMap와 같지 TreeMap않지만 Collections.synchronizedMap()순서는 유지됩니다.

또한 한 스레드가 맵을 업데이트하고 다른 스레드가 맵에서 얻은 반복자를 통과하는 동안 발생 ConcurrentHashMap하지 않는 것을 보장 할 수 있습니다 ConcurrentModificationException. 그러나 Collections.synchronizedMap()이것에 대해서는 보장되지 않습니다.

일 이후 이 두도의 차이를 보여줍니다 ConcurrentSkipListMap.


답변

동기화 된 맵 :

동기화 맵은 Hashtable과 크게 다르지 않으며 동시 Java 프로그램에서 유사한 성능을 제공합니다. Hashtable과 SynchronizedMap의 차이점은 SynchronizedMap이 레거시가 아니며 Collections.synchronizedMap () 메소드를 사용하여 동기화 된 버전을 작성하기 위해 모든 맵을 랩핑 할 수 있다는 것입니다.

동시 해시 맵 :

ConcurrentHashMap 클래스는 표준 HashMap의 동시 버전을 제공합니다. 이것은 Collections 클래스에서 제공되는 synchronizedMap 기능이 개선되었습니다.

해시 테이블 및 동기화 맵과 달리 맵 전체를 잠그지 않고 맵을 세그먼트로 나누고 잠금을 수행합니다. 리더 스레드 수가 쓰기 스레드 수보다 많으면 성능이 더 좋습니다.

ConcurrentHashMap은 기본적으로 16 개의 영역으로 구분되며 잠금이 적용됩니다. ConcurrentHashMap 인스턴스를 초기화하는 동안이 기본 숫자를 설정할 수 있습니다. 특정 세그먼트에서 데이터를 설정하면 해당 세그먼트에 대한 잠금이 설정됩니다. 이는 두 개의 업데이트가 각각 별도의 버킷에 영향을주는 경우에도 동시에 안전하게 실행되어 잠금 경합을 최소화하고 성능을 최대화 할 수 있음을 의미합니다.

ConcurrentHashMap은 ConcurrentModificationException을 발생시키지 않습니다.

한 스레드가 다른 스레드가이를 반복하는 동안이를 수정하려고하면 ConcurrentHashMap은 ConcurrentModificationException을 발생시키지 않습니다.

synchornizedMap과 ConcurrentHashMap의 차이점

Collections.synchornizedMap (HashMap)은 Hashtable과 거의 동일한 컬렉션을 반환합니다. ConcurrentHashMap의 경우 Map의 모든 수정 작업이 Map 객체에서 잠기는 반면 동시성 수준에 따라 전체 Map을 다른 파티션으로 나눔으로써 스레드 안전성이 달성됩니다. 전체지도를 잠그는 대신 특정 부분 만 잠그는 것입니다.

ConcurrentHashMap은 null 키 또는 null 값을 허용하지 않지만 동기화 된 HashMap은 하나의 null 키를 허용합니다.

비슷한 링크

링크 1

링크 2

성능 비교


답변

평상시와 같이 동시성 (오버 헤드) 속도 상충 관계가 있습니다. 결정을 내리려면 응용 프로그램의 자세한 동시성 요구 사항을 고려해야합니다. 그런 다음 코드가 충분한 지 테스트해야합니다.