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


607

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

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

  • Hashtable
  • Collections.synchronizedMap(Map)
  • ConcurrentHashMap

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

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


7
@SmilesinaJar 링크가 현재 고장났습니다. 다음은이 기사의 아카이브 사본입니다. ConcurrentHashMap이 Hashtable보다 우수하고 HashMap만큼 좋은 이유
informatik01

2
IBM : @ 스레드 안전을 손상시키지 않고 어떻게 ConcurrentHashMap의이 제안 높은 동시성을 ibm.com/developerworks/java/library/j-jtp08223/...
pramodc84

참고로 Java 6은 ConcurrentSkipListMap또 다른 스레드 안전 Map구현을 가져 왔습니다 . 건너 뛰기 목록 알고리즘을 사용하여로드시 고도로 동시 설계되었습니다 .
Basil Bourque

답변:


423

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

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


8
소스 코드를 살펴보면, 동기화 된 맵은 하나의 뮤텍스 (차단) 만있는 구현이지만 ConcurrentHashMap은 동시 액세스를 처리하기가 더 복잡합니다.
Vinze

123
ConcurrentHashMap은 널 키 또는 값을 허용하지 않습니다. 따라서 동기화 된 맵의 대안이 아닙니다.
onejigtwojig

24
나는 당신이 이것을 읽어야한다고 생각합니다 http://ria101.wordpress.com/2011/12/12/concurrenthashmap-avoid-a-common-misuse/
Mr Spark

5
그 기사에서 제기 @AbdullahShaikh 문제가 자바 7에서 수정되었습니다 및 추가 개선은 자바 8. 이루어지고있다
pulse0ne

5
@hengxin : 맵의 여러 쿼리 또는 업데이트로 구성된 작업을 수행하거나 맵을 반복하는 경우 맵을 수동으로 동기화하여 일관성을 유지해야합니다. 동기화 된 맵은 맵에서 단일 작업 (메소드 호출)에 대해서만 일관성을 보장하므로 대부분의 실제 작업이 중요하지 않으므로 아무리 가치가 없어도 수동으로 동기화해야합니다.
Holger

241
╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║   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잠금 단 버킷 .


13
Hashtable지도의 일부를 잠그지 않습니다. 구현을보십시오. synchronized잠금이없는 키를 사용 하므로 기본적으로 hashtable각 작업에서 전체 를 잠그는 것을 의미합니다 .
RMachnik

6
synchronizedMap은 어떻습니까?
Samuel Edwin Ward

3
방법은 스레드 안전 모든 제외 Collections.syncronizedMap 동작은, 기본으로되어있는 맵과 같다
Sergii Shevchyk

5
나는 테이블을 인쇄하고 각 $ 5를 위해 팔 것이다;). 좋은 것 @shevchyk
realPK

편집 : 스레드 안전이 전혀 없습니다. 새로운 개발자에게는 약간의 오해의 소지가 있습니다. ConcurrentHashMap조차도 외부 데이터 레이스에서 스레드로부터 안전하지 않다는 것을 이해하려면 ibm.com/developerworks/java/library/j-jtp07233/index.html 을 참조하십시오 . (예 : 1 스레드는 값을 제거하고 다른 스레드는 값이 존재하는지 여부를 확인하려고 시도합니다. 이는 데이터 경쟁 조건이며 여전히 "ConcurrentHashMap"을 사용하더라도 모든 스레드 안전 문제를 완화하지는 않습니다.
좀비

142

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

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

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


4
이제 내가 원하는 것입니다! :) 동기화되지 않은 반복자는 순수한 단맛 만 있습니다! 정보 감사합니다! :) (:
Kounavi 2016 년

훌륭한 답변 .. 그러나 검색 스레드가 독자 스레드가 동기화되지 않기 때문에 최신 업데이트를 얻지 못한다는 것을 의미합니다.
MrA

@MrA : ConcurrentHashMap에 대해 질문하고 있습니까? 그리고 "검색"은 무엇을 의미합니까?
Michael Borgwardt

4
예를 들어 ConcurrentHashmap을위한 @Michael Borgwardt. 여러 스레드가 있다고 가정하십시오. 그들 중 일부는지도를 업데이트하고 일부는 동일한지도에서 데이터를 가져옵니다. 따라서이 시나리오에서 스레드를 읽으려고 할 때 독자 스레드가 잠금을 보유 할 필요가 없으므로 업데이트 된 최신 데이터를 얻을 수 있습니다.
MrA

35

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

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

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

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


2
네, 제가 대답 할 때마다 그 책을 언급 한 것 같습니다!
Bill Michell

@BillMichell 링크가 끊어졌습니다

@Govinda 링크에 액세스하기 전에 자바 스크립트를 끄십시오. 블로그 항목은 여전히 ​​존재합니다!
Bill Michell

32

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

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

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

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


13

동기화 된 맵 :

동기화 맵은 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

성능 비교


12

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


12

에서 ConcurrentHashMap잠금이 세그먼트 대신의 전체지도에 적용됩니다. 각 세그먼트는 자체 내부 해시 테이블을 관리합니다. 잠금은 업데이트 작업에만 적용됩니다. Collections.synchronizedMap(Map)전체지도를 동기화합니다.



9

당신은 맞습니다 HashTable. 잊어 버릴 수 있습니다.

이 기사 에서는 HashTable과 동기화 된 래퍼 클래스가 한 번에 하나의 스레드 만 맵에 액세스하도록 허용하여 기본 스레드 안전성을 제공하지만 많은 복합 작업에는 여전히 추가 동기화가 필요하기 때문에 '실제'스레드 안전성이 아니라는 사실을 언급했습니다. 예:

synchronized (records) {
  Record rec = records.get(id);
  if (rec == null) {
      rec = new Record(id);
      records.put(id, rec);
  }
  return rec;
}

그러나 위와 같이 일반적인 블록 ConcurrentHashMap이있는 간단한 대안 이라고 생각하지 마십시오 . 기사를 읽고 그 복잡성을 더 잘 이해하십시오.HashMapsynchronized


7

몇 가지가 있습니다 :

1) ConcurrentHashMap은 Map의 일부만 잠그지 만 SynchronizedMap은 전체 MAp를 잠급니다.
2) ConcurrentHashMap은 SynchronizedMap보다 성능이 뛰어나고 확장 성이 뛰어납니다.
3) 다중 리더 및 단일 라이터의 경우 ConcurrentHashMap이 최선의 선택입니다.

이 텍스트는 Java의 ConcurrentHashMap과 해시 테이블의 차이점입니다.


7

ConcurrentHashMap과 synchronisedHashmap 및 Hashtable을 사용하여 스레드 안전성을 달성 할 수 있습니다. 그러나 아키텍처를 살펴보면 많은 차이가 있습니다.

  1. 동기화 된 해시 맵 및 해시 테이블

둘 다 잠금을 객체 수준으로 유지합니다. 따라서 put / get과 같은 작업을 수행하려면 먼저 잠금을 획득해야합니다. 동시에 다른 스레드는 어떤 작업도 수행 할 수 없습니다. 따라서 한 번에 하나의 스레드만이 작동 할 수 있습니다. 따라서 대기 시간이 증가합니다. ConcurrentHashMap과 비교할 때 성능이 상대적으로 낮다고 말할 수 있습니다.

  1. 동시 해시 맵

잠금은 세그먼트 레벨에서 유지됩니다. 16 개의 세그먼트가 있으며 동시성 수준은 기본적으로 16으로 유지됩니다. 따라서 한 번에 16 개의 스레드가 ConcurrentHashMap에서 작동 할 수 있습니다. 또한 읽기 작업에는 잠금이 필요하지 않습니다. 따라서 많은 수의 스레드가 get 작업을 수행 할 수 있습니다.

thread1이 세그먼트 2에서 넣기 조작을 수행하고 thread2가 세그먼트 4에서 넣기 조작을 수행하려는 경우 여기에서 허용됩니다. 즉, 16 개의 스레드가 ConcurrentHashMap에서 한 번에 업데이트 (put / delete) 작업을 수행 할 수 있습니다.

대기 시간이 줄어들 것입니다. 따라서 성능이 동기화 된 해시 맵 및 해시 테이블보다 상대적으로 우수합니다.


1
,1. 여러 스레드가 동일한 블록을 편집하려고하면 어떻게됩니까? 2. 두 스레드가 동시에 데이터를 쓰는 경우 다른 스레드가있는 동일한 블록에서 데이터를 읽으려고하면 어떻게됩니까?
prnjn

6

동시 해시 맵

  • 프로젝트에서 매우 높은 동시성이 필요한 경우 ConcurrentHashMap을 사용해야합니다.
  • 전체 맵을 동기화하지 않고 스레드로부터 안전합니다.
  • 쓰기가 잠금으로 수행되는 동안 읽기가 매우 빠르게 발생할 수 있습니다.
  • 객체 레벨에는 잠금이 없습니다.
  • 잠금은 해시 맵 버킷 수준에서 훨씬 세분화됩니다.
  • 한 스레드가 다른 스레드가이를 반복하는 동안이를 수정하려고하면 ConcurrentHashMap은 ConcurrentModificationException을 발생시키지 않습니다.
  • ConcurrentHashMap은 다수의 잠금을 사용합니다.

SynchronizedHashMap

  • 객체 수준에서의 동기화.
  • 모든 읽기 / 쓰기 작업은 잠금을 획득해야합니다.
  • 전체 컬렉션을 잠그면 성능 오버 헤드가 발생합니다.
  • 이것은 기본적으로 하나의 스레드에만 전체 맵에 대한 액세스를 제공하고 다른 모든 스레드를 차단합니다.
  • 경합이 발생할 수 있습니다.
  • SynchronizedHashMap은 Iterator를 반환하며, 이는 동시에 수정하면 실패합니다.

출처


4

ConcurrentHashMap은 동시 액세스에 최적화되어 있습니다.

액세스는 전체 맵을 잠그지 않지만보다 세분화 된 전략을 사용하여 확장 성을 향상시킵니다. 동시 액세스를위한 기능 향상이 있습니다 (예 : 동시 반복자).


4

하나 개의 중요한 기능 에 대해 주목해야 할 ConcurrentHashMap것입니다 그것이 제공하는 동시성 기능 이외의 안전 장치 반복자. 개발자 ConcurrentHashMap가 항목 세트를 편집하기를 원하기 때문에 사용하는 것을 보았습니다 . Collections.synchronizedMap(Map)제공하지 않습니다 페일 세이프 (fail-safe) 반복자를하지만, 제공 르파 반복자를 대신. fail-fast iterators는 반복 중에 편집 할 수없는 맵 크기의 스냅 샷을 사용합니다.


3
  1. 데이터 일관성이 매우 중요한 경우-Hashtable 또는 Collections.synchronizedMap (Map)을 사용하십시오.
  2. 속도 / 성능이 매우 중요하고 데이터 업데이트가 손상 될 수있는 경우 ConcurrentHashMap을 사용하십시오.

2

당신이 사용하려는 경우 일반적으로, ConcurrentHashMap확인을 당신이 '업데이트'미스 준비가
같이 사용하는 API (가 최신의지도를 인쇄 할 수 있도록하지 않습니다 즉, HashMap의 내용을 인쇄) CyclicBarrier프로그램 년대에 걸쳐 일관성을 보장하기는 수명주기.


1

Collections.synchronizedMap () 메소드는 HashMap의 모든 메소드를 동기화하고 공통 잠금에서 모든 메소드를 잠그기 때문에 한 스레드가 한 번에 입력 할 수있는 데이터 구조로 효과적으로 줄입니다.

ConcurrentHashMap에서 동기화는 약간 다르게 수행됩니다. ConcurrentHashMap은 공통 잠금에서 모든 메소드를 잠그지 않고 별도의 버킷에 별도의 잠금을 사용하므로 맵의 일부만 잠급니다. 기본적으로 16 개의 버킷과 별도의 버킷에 대한 별도의 잠금 장치가 있습니다. 따라서 기본 동시성 수준은 16입니다. 이론적으로 16 개의 스레드가 모두 버킷을 분리 할 경우 ConcurrentHashMap에 액세스 할 수 있습니다.


1

ConcurrentHashMap은 동시성 패키지의 일부로 Java 1.5에서 Hashtable의 대안으로 제공되었습니다. ConcurrentHashMap을 사용하면 동시 다중 스레드 환경에서 안전하게 사용할 수있을뿐만 아니라 Hashtable 및 synchronizedMap보다 더 나은 성능을 제공하는 경우 더 나은 선택이 가능합니다. ConcurrentHashMap은 Map의 일부를 잠그기 때문에 더 잘 수행됩니다. 동시 읽기 작업을 허용하고 동시에 쓰기 작업을 동기화하여 무결성을 유지합니다.

ConcurrentHashMap이 구현되는 방법

ConcurrentHashMap은 Hashtable의 대안으로 개발되었으며 동시성 수준이라고하는 추가 기능으로 Hashtable의 모든 기능을 지원합니다. ConcurrentHashMap을 사용하면 여러 독자가 블록을 사용하지 않고 동시에 읽을 수 있습니다. Map을 다른 부분으로 분리하고 업데이트에서 Map의 일부만 차단하면 가능합니다. 기본적으로 동시성 수준은 16이므로 맵은 16 개의 부분으로 구성되며 각 부분은 분리 된 블록으로 관리됩니다. 즉, 16 개의 스레드가 Map의 다른 부분에서 작동하는 경우 Map과 동시에 작동 할 수 있습니다. ConcurrentHashMap은 생산성을 높이고 스레드 안전성을 떨어 뜨리지 않습니다.

ConcurrentHashMap의 몇 가지 중요한 기능에 관심이 있고이 맵 구현을 사용해야 할 때-좋은 기사로 연결되는 링크 -Java에서 ConcurrentHashMap 사용 방법


0

제안 된 것 외에도에 관련된 소스 코드를 게시하고 싶습니다 SynchronizedMap.

Map스레드를 안전하게 만들기 위해 Collections.synchronizedMapstatement 를 사용 하고 맵 인스턴스를 매개 변수로 입력 할 수 있습니다 .

의 구현 synchronizedMap에는 Collections다음과 같다

   public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
        return new SynchronizedMap<>(m);
    }

보시다시피 입력 Map객체는 객체로 래핑됩니다 SynchronizedMap.
의 구현에 대해 알아 보자 SynchronizedMap.

 private static class SynchronizedMap<K,V>
        implements Map<K,V>, Serializable {
        private static final long serialVersionUID = 1978198479659022715L;

        private final Map<K,V> m;     // Backing Map
        final Object      mutex;        // Object on which to synchronize

        SynchronizedMap(Map<K,V> m) {
            this.m = Objects.requireNonNull(m);
            mutex = this;
        }

        SynchronizedMap(Map<K,V> m, Object mutex) {
            this.m = m;
            this.mutex = mutex;
        }

        public int size() {
            synchronized (mutex) {return m.size();}
        }
        public boolean isEmpty() {
            synchronized (mutex) {return m.isEmpty();}
        }
        public boolean containsKey(Object key) {
            synchronized (mutex) {return m.containsKey(key);}
        }
        public boolean containsValue(Object value) {
            synchronized (mutex) {return m.containsValue(value);}
        }
        public V get(Object key) {
            synchronized (mutex) {return m.get(key);}
        }

        public V put(K key, V value) {
            synchronized (mutex) {return m.put(key, value);}
        }
        public V remove(Object key) {
            synchronized (mutex) {return m.remove(key);}
        }
        public void putAll(Map<? extends K, ? extends V> map) {
            synchronized (mutex) {m.putAll(map);}
        }
        public void clear() {
            synchronized (mutex) {m.clear();}
        }

        private transient Set<K> keySet;
        private transient Set<Map.Entry<K,V>> entrySet;
        private transient Collection<V> values;

        public Set<K> keySet() {
            synchronized (mutex) {
                if (keySet==null)
                    keySet = new SynchronizedSet<>(m.keySet(), mutex);
                return keySet;
            }
        }

        public Set<Map.Entry<K,V>> entrySet() {
            synchronized (mutex) {
                if (entrySet==null)
                    entrySet = new SynchronizedSet<>(m.entrySet(), mutex);
                return entrySet;
            }
        }

        public Collection<V> values() {
            synchronized (mutex) {
                if (values==null)
                    values = new SynchronizedCollection<>(m.values(), mutex);
                return values;
            }
        }

        public boolean equals(Object o) {
            if (this == o)
                return true;
            synchronized (mutex) {return m.equals(o);}
        }
        public int hashCode() {
            synchronized (mutex) {return m.hashCode();}
        }
        public String toString() {
            synchronized (mutex) {return m.toString();}
        }

        // Override default methods in Map
        @Override
        public V getOrDefault(Object k, V defaultValue) {
            synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
        }
        @Override
        public void forEach(BiConsumer<? super K, ? super V> action) {
            synchronized (mutex) {m.forEach(action);}
        }
        @Override
        public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
            synchronized (mutex) {m.replaceAll(function);}
        }
        @Override
        public V putIfAbsent(K key, V value) {
            synchronized (mutex) {return m.putIfAbsent(key, value);}
        }
        @Override
        public boolean remove(Object key, Object value) {
            synchronized (mutex) {return m.remove(key, value);}
        }
        @Override
        public boolean replace(K key, V oldValue, V newValue) {
            synchronized (mutex) {return m.replace(key, oldValue, newValue);}
        }
        @Override
        public V replace(K key, V value) {
            synchronized (mutex) {return m.replace(key, value);}
        }
        @Override
        public V computeIfAbsent(K key,
                Function<? super K, ? extends V> mappingFunction) {
            synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
        }
        @Override
        public V computeIfPresent(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
        }
        @Override
        public V compute(K key,
                BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.compute(key, remappingFunction);}
        }
        @Override
        public V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
            synchronized (mutex) {return m.merge(key, value, remappingFunction);}
        }

        private void writeObject(ObjectOutputStream s) throws IOException {
            synchronized (mutex) {s.defaultWriteObject();}
        }
    }

무엇 SynchronizedMap입력의 기본 방법에 단일 잠금 추가로 요약 될 수 않는 Map개체. 잠금에 의해 보호 된 모든 메소드는 동시에 여러 스레드에 의해 액세스 될 수 없습니다. 즉 , 개체의 모든 데이터에 대해 단일 스레드 put와 같은 일반적인 작업 get을 동시에 수행 할 수 있습니다 Map.

그것은 만드는 Map지금 오브젝트 스레드 안전하지만, 성능은 일부 시나리오에서 문제가 될 수 있습니다.

ConcurrentMap훨씬 더 구현에 복잡, 우리가 참조 할 수 있습니다 더 나은 HashMap의 구축 자세한 내용은. 간단히 말해서 스레드 안전성과 성능을 모두 고려하여 구현되었습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.