[java] ConcurrentHashMap이 널 키와 값을 방지하는 이유는 무엇입니까?

의 JavaDoc ConcurrentHashMap은 다음 과 같이 말합니다.

마찬가지로 Hashtable하지만 달리 HashMap,이 클래스는 않습니다 하지 있도록 null키 또는 값으로 사용할 수 있습니다.

내 질문 : 왜?

두 번째 질문 : 왜 Hashtablenull을 허용 하지 않습니까?

데이터를 저장하기 위해 많은 HashMap을 사용했습니다. 그러나 ConcurrentHashMapNullPointerExceptions로 변경하면 여러 번 문제가 발생했습니다.



답변

ConcurrentHashMap자신 의 저자 (Doug Lea)의 :

ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps)에서 널이 허용되지 않는 주된 이유는 비 동시 맵에서 거의 허용되지 않는 모호성을 수용 할 수 없기 때문입니다. 주요한 것은 map.get(key)return을 반환 null하면 키가 명시 적으로 매핑되고 null키가 매핑되지 않았 는지 여부를 감지 할 수 없다는 것 입니다. 비 동시 맵에서는을 통해이를 확인할 수
map.contains(key)있지만 동시에 맵에서는 통화간에 맵이 변경되었을 수 있습니다.


답변

나는, 적어도 부분적으로, 당신이 결합 할 수 있도록 생각 containsKey하고 get단일 통화로. 맵이 널을 보유 할 수있는 경우 get해당 값에 대한 키가 없거나 값이 널이어서 널을 리턴 하는지 여부를 알 수있는 방법 이 없습니다.

왜 문제가 되나요? 그렇게 할 수있는 안전한 방법이 없기 때문입니다. 다음 코드를 사용하십시오.

if (m.containsKey(k)) {
   return m.get(k);
} else {
   throw new KeyNotPresentException();
}

이후 m동시 맵, 키 k는 사이에 삭제 될 수 있습니다 containsKey그리고 get오히려 원하는 것보다 표에 결코 널을 반환하는이 조각을 일으키는 통화 KeyNotPresentException.

일반적으로 동기화를 통해 문제를 해결할 수 있지만 동시 맵으로는 작동하지 않습니다. 따라서 서명 get을 변경해야하며 이전 버전과 호환되는 방법으로 사용자가 처음에 null 값을 삽입하지 못하게하고 “키를 찾을 수 없음”의 자리 표시 자로 계속 사용하는 것이 유일한 방법이었습니다.


답변

Josh Bloch 설계 HashMap; 더그 레아 디자인 ConcurrentHashMap. 나는 그것이 사소하지 않기를 바랍니다. 실제로 문제는 null이 종종 랩핑을 요구하여 실제 null이 초기화되지 않았 음을 나타낼 수 있다고 생각합니다. 클라이언트 코드에 널이 필요한 경우 널 자체 랩핑 비용 (소액이 적음)을 지불 할 수 있습니다.


답변

null에서는 동기화 할 수 없습니다.

편집 : 이것은이 경우에 정확하게 이유가 아닙니다. 처음에는 동시 업데이트에 대해 잠금을 설정하거나 객체 모니터를 사용하여 무언가 수정되었는지 감지하는 데 멋진 일이 있다고 생각했지만 소스 코드 를 검사 때 잘못된 것으로 보입니다. 해시의 비트 마스크.

이 경우 Hashtable을 복사하기 위해 수행 한 것으로 의심되며 관계형 데이터베이스 세계에서는 null! = null이므로 Hashtable이 수행 한 것으로 생각되므로 null을 키로 사용하는 것은 의미가 없습니다.


답변

ConcurrentHashMap은 스레드로부터 안전합니다. null 키와 값을 허용하지 않는 것이 스레드 안전을 보장하는 일부라고 생각합니다.


답변

API 문서의 다음 스 니펫은 좋은 힌트를 제공한다고 생각합니다. “이 클래스는 스레드 안전에 의존하지만 동기화 세부 사항에는 의존하지 않는 프로그램에서 Hashtable과 완전히 상호 운용 가능합니다.”

그들은 아마도 ConcurrentHashMap완벽하게 호환 가능하고 교환 가능하게 만들고 싶을 것입니다 Hashtable. 그리고 Hashtablenull 키와 값을 허용하지 않습니다.


답변

null 값을 허용하지 않는 것이 올바른 옵션이라고 생각하지 않습니다. 많은 경우에, 우리는 동시 맵에 null 값을 가진 키를 넣기를 원합니다. 그러나 ConcurrentHashMap을 사용하면 그렇게 할 수 없습니다. 앞으로 출시 될 JDK 버전이이를 지원할 수 있다고 제안합니다.