래퍼 클래스를 사용하는 것의 차이점은 무엇입니까? SynchronizedMap
A의, HashMap
그리고 ConcurrentHashMap
?
HashMap
반복 하는 동안 ( ConcurrentHashMap
) 을 수정할 수 있습니까?
래퍼 클래스를 사용하는 것의 차이점은 무엇입니까? SynchronizedMap
A의, HashMap
그리고 ConcurrentHashMap
?
HashMap
반복 하는 동안 ( ConcurrentHashMap
) 을 수정할 수 있습니까?
답변:
동기화 HashMap
:
각 메소드는 오브젝트 레벨 잠금을 사용하여 동기화됩니다. 따라서 synchMap의 get 및 put 메소드는 잠금을 획득합니다.
전체 컬렉션을 잠그면 성능 오버 헤드가 발생합니다. 하나의 스레드가 잠금을 유지하는 동안 다른 스레드는 콜렉션을 사용할 수 없습니다.
ConcurrentHashMap
JDK 5에 도입되었습니다.
객체 레벨에는 잠금이 없으며, 잠금은 훨씬 세밀합니다. 의 경우 ConcurrentHashMap
잠금은 해시 맵 버킷 수준 일 수 있습니다.
하위 레벨 잠금의 효과는 동기화 된 콜렉션에 대해 불가능한 동시 판독기 및 기록기를 가질 수 있다는 것입니다. 이것은 훨씬 더 확장 성을 가져옵니다.
ConcurrentHashMap
ConcurrentModificationException
한 스레드가 스레드를 수정하려고 시도하는 동안 다른 스레드가 스레드를 수정하려고 시도하면 if를 던지지 않습니다 .
이 기사 Java 7 : HashMap vs ConcurrentHashMap 은 매우 잘 읽습니다. 추천.
ConcurrentHashMap
의 size()
결과가 오래 되었을 수 있습니다. size()
"실제 Java 동시성"책에 따라 정확한 수 대신 근사값을 반환 할 수 있습니다. 따라서이 방법을주의해서 사용해야합니다.
짧은 대답 :
두 맵 모두 Map
인터페이스 의 스레드 안전 구현입니다 . ConcurrentHashMap
높은 동시성이 예상되는 경우 더 높은 처리량을 위해 구현됩니다.
아이디어 뒤에 관한 Brian Goetz의 기사ConcurrentHashMap
는 아주 잘 읽었습니다. 추천.
Map m = Collections.synchronizedMap(new HashMap(...));
docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
ConcurrentHashMap과 synchronisedHashmap을 모두 사용하여 스레드 안전성을 얻을 수 있습니다. 그러나 아키텍처를 살펴보면 많은 차이가 있습니다.
잠금은 객체 수준에서 유지됩니다. 따라서 put / get과 같은 작업을 수행하려면 먼저 잠금을 획득해야합니다. 동시에 다른 스레드는 어떤 작업도 수행 할 수 없습니다. 따라서 한 번에 하나의 스레드만이 작동 할 수 있습니다. 따라서 대기 시간이 증가합니다. ConcurrentHashMap과 비교할 때 성능이 상대적으로 낮다고 말할 수 있습니다.
잠금은 세그먼트 레벨에서 유지됩니다. 16 개의 세그먼트가 있으며 동시성 수준은 기본적으로 16으로 유지됩니다. 따라서 한 번에 16 개의 스레드가 ConcurrentHashMap에서 작동 할 수 있습니다. 또한 읽기 작업에는 잠금이 필요하지 않습니다. 따라서 많은 수의 스레드가 get 작업을 수행 할 수 있습니다.
thread1이 세그먼트 2에서 넣기 조작을 수행하고 thread2가 세그먼트 4에서 넣기 조작을 수행하려는 경우 여기에서 허용됩니다. 즉, 16 개의 스레드가 ConcurrentHashMap에 대해 한 번에 업데이트 (put / delete) 작업을 수행 할 수 있습니다.
대기 시간이 줄어들 것입니다. 따라서 성능이 동기화 된 해시 맵보다 상대적으로 우수합니다.
둘 다 핵심 기능과 내부 구조가 다른 HashMap의 동기화 버전입니다.
ConcurrentHashMap 은 독립적 인 HashMaps 개념적으로 볼 수있는 내부 세그먼트로 구성됩니다. 이러한 모든 세그먼트는 동시 실행시 별도의 스레드로 잠글 수 있습니다. 따라서 여러 스레드가 서로를 차단 / 대기하지 않고 ConcurrentHashMap에서 키-값 쌍을 가져 오거나 넣을 수 있습니다. 이것은 높은 처리량을 위해 구현됩니다.
이므로
Collections.synchronizedMap () , 우리는 동기화 된 버전의 HashMap을 얻으며 차단 방식으로 액세스됩니다. 이는 여러 스레드가 동시에 synchronizedMap에 액세스하려고하면 키-값 쌍을 동기화 된 방식으로 한 번에 하나씩 가져 오거나 입력 할 수 있음을 의미합니다.
ConcurrentHashMap
lock stripping
보다 높은 수준의 공유 액세스를 허용 하는 것으로 알려진보다 세밀한 잠금 메커니즘 을 사용합니다. 이로 인해 더 나은 동시성 및 확장 성을 제공 합니다.
또한 반환 반복자 ConcurrentHashMap
입니다 약 일관성 대신 빠른 기술 실패 동기화 된 HashMap에 의해 사용합니다.
메소드 SynchronizedMap
는 객체의 잠금 을 유지하는 반면 ConcurrentHashMap
, 잠금은 내용의 버킷에 대신 고정되는 "잠금 스트라이핑"개념이 있습니다. 따라서 확장 성과 성능이 향상되었습니다.
ConcurrentHashMap 은 데이터에 대한 동시 액세스를 허용합니다. 전체지도는 세그먼트로 나뉩니다.
읽기 작업 즉. get(Object key)
세그먼트 수준에서도 동기화되지 않습니다.
그러나 쓰기 작업 즉. remove(Object key), get(Object key)
세그먼트 레벨에서 잠금을 획득하십시오. 전체 맵의 일부만 잠기고 다른 스레드는 여전히 잠긴 것을 제외한 다양한 세그먼트의 값을 읽을 수 있습니다.
반면에 SynchronizedMap 은 객체 레벨에서 잠금을 획득합니다. 모든 스레드는 작업 (읽기 / 쓰기)에 관계없이 현재 스레드를 기다려야합니다.
동기화 된 HashMap에 대 ConcurrentHashMap의에 대한 간단한 성능 테스트
. 테스트 흐름은 put
하나의 스레드에서 호출 get
되고 Map
동시에 세 개의 스레드에서 호출 됩니다. @trshiv가 말했듯이 ConcurrentHashMap은 잠금이없는 읽기 작업의 처리량과 속도가 높습니다. 결과는 작업 시간이 초과 10^7
되면 ConcurrentHashMap이 2x
Synchronized HashMap보다 빠릅니다.
SynchronizedMap
그리고 ConcurrentHashMap
두 스레드 안전 클래스이며, 그들 사이의 주요 차이점은 그들이 스레드 안전을 달성하는 방법에 대한되는 다중 스레드 응용 프로그램에서 사용할 수 있습니다.
SynchronizedMap
전체 Map 인스턴스에서 잠금을 획득 ConcurrentHashMap
하고 Map 인스턴스를 여러 세그먼트로 나누고 잠금을 수행합니다.
자바 의사에 따라
Hashtable과 Collections.synchronizedMap (new HashMap ())이 동기화됩니다. 그러나 ConcurrentHashMap은 "concurrent"입니다.
동시 콜렉션은 스레드로부터 안전하지만 단일 제외 잠금으로 관리되지 않습니다.
ConcurrentHashMap의 특정 경우에는 여러 개의 동시 읽기와 조정 가능한 수의 동시 쓰기를 안전하게 허용합니다. "동기화 된"클래스는 확장 성이 떨어지는 대신 단일 잠금을 통해 컬렉션에 대한 모든 액세스를 방지해야 할 때 유용 할 수 있습니다.
다중 스레드가 공통 콜렉션에 액세스 할 것으로 예상되는 다른 경우에는 일반적으로 "동시"버전이 선호됩니다. 동기화되지 않은 컬렉션은 컬렉션 중 하나를 공유하지 않거나 다른 잠금을 보유한 경우에만 액세스 할 수있는 경우에 바람직합니다.
Hashtable
와 의 차이점은 무엇Synchronized HashMap
입니까?