2012-08-30 7 views
2

저는 자바로 쓰레딩을하는 것을 처음 접했고 몇몇 활성 스레드에서 데이터 구조에 액세스해야합니다. java.util.concurrent.ConcurrentHashMap이 스레딩 용이라고 들었습니다. ConcurrentHashMap에 액세스하는 동안 synchronized(map){} 을 사용해야합니까, 아니면 잠금 자체를 처리합니까?ConcurrentHashMap 사용하기

답변

4

이 잠금 자체를 처리하고 사실에 당신은 당신이 쓰기에 대한 특별한 경우 synchronized을 사용할 수 있습니다

(거기에 다른 옵션은 없음), 그러나 당신이 필요합니다 매우 드문 그들에 액세스 할 수 없습니다 이 작업을 수행. 예 : 자신의 putIfAbsent을 구현해야하는 경우 객체를 만드는 비용이 높기 때문입니다.

읽기에 syncrhonized를 사용하면 동시 수집을 사용하는 목적을 무효화 할 수 있습니다.

+2

또한 putIfAbsent는 원자 적으로 수행되기 때문에 어떤 경우에는 매우 유용합니다. – stemm

2

짧은 대답 : 아니오 synchronized(map)을 사용할 필요가 없습니다.
긴 대답 : ConcurrentHashMap에서 제공

  • 모든 작업은 스레드로부터 안전하고 당신이 당신의 코드에서 원자 할 몇 가지 작업을해야 할 경우 당신은 당신은 여전히 ​​필요합니다, 그러나
  • 잠금에 대한 걱정없이 그들을 호출 할 수 있습니다 클라이언트 측
2

없음에 잠금 어떤 종류의, 당신은 필요하지 않습니다,하지만 당신은 내부 동기화에 의존해야하는 경우, 대신 Collections.synchronizedMap를 사용해야합니다. ConcurrentHashMap의 자바 독에서 :

이 클래스는 스레드 안전에 있지만 그 동기 정보에 의존하는 프로그램에서 해시 테이블과 완벽하게 상호 운용이다.

실제로 전체 데이터 구조에서는 동기화되지 않지만 일부 데이터 항목 (일부 버킷)에서는 동기화되지 않습니다. 이것은 ConcurrentHashMap의 반복기가 약하게 일관되고지도의 크기가 부정확 할 수 있음을 의미합니다. (하지만 다른 한편으로는 작업을 가져오고 처리량은 더 높습니다.)

+0

왜 누군가가지도에서'.size()'를 사용해야합니까? 'values ​​()'와'keySet()'가 크기와 같은 방식으로 부정확 할 수 있습니까? – dantuch

+0

@duchuch 아니요 - 예를 들어 javadoc의 값은 다음과 같습니다. * "콜렉션은 맵에 의해 백업되므로 맵 변경 사항은 콜렉션에 반영되며 그 반대의 경우도 마찬가지입니다."* – assylias

3

ConcurrentHashMap은 기본 제공되는 것보다 더 이상 원 자성을 필요로하지 않는 경우에만 적합합니다. 예를 들어 값을 가져와 무언가를 수행 한 다음 새로운 값을 설정해야하는 경우 (모두 원 자성 조작으로 수행)이 경우 외부 잠금 없이는 달성 할 수 없습니다.

이 모든 경우에 코드의 명시 적 잠금을 대체 할 수있는 것은 없으며 기본 HashMap 대신이 구현을 사용하는 것이 낭비 일뿐입니다.

-1

안전 반복자 실패이다가 제공하는 동시성 기능 이외의 concurrenthmp 에 대한주의하는 것이 또 하나의 중요한 기능 있습니다. 반복하는 동안 put/remove에 대한 엔트리 세트를 편집하기를 원하기 때문에 CHMP를 사용하십시오. Collections.synchronizedMap(Map)은 다른 것입니다. 그러나 ConcurrentModificationException이 위의 경우에 올 수 있습니다.