2017-09-19 1 views
1

객체 (예 : HashMap 또는 ArrayList 또는 POJO)가 단일 (동일한) 스레드에 의해 항상 수정 될 때 스레드 안전성을 달성하기위한 일반적인 접근법은 무엇입니까? 여러 스레드에서 액세스 할 수 있습니까?Java : 단일 스레드에서 객체 수정, 다중 스레드 읽기

HashMap은 나에게 가장 관심이 있지만 일반적인 접근 방식이 필요합니다.

휘발성으로 충분합니까?

감사합니다.

+1

아니요, 휘발성이 충분하지 않습니다. 변수가 재 할당 될 때 동기화 만 발생하므로 단일 맵/목록의 경우 결코 그렇지 않습니다. 'java.util.concurrent'에서'ReadWriteLock'과 같은 내부 또는 외부 잠금이 필요합니다. 그것들은 특정 절충점을 부과 함을 명심하십시오. 각각의 javadoc에 더 있습니다. –

답변

1

아마도 ConcurrentHashMap을 살펴 봐야 할 것입니다.

공용 클래스 ConcurrentHashMap의

은 취득에서는 업데이트에 대한 높은 기대의 완전한 동시성의 동시성을 지원하는 해시 테이블

직렬화,

가 인 ConcurrentMap를 구현하고 AbstractMap을 확장한다. 이 클래스는 Hashtable과 동일한 기능 스펙을 따르며 Hashtable의 각 메소드에 해당하는 메소드 버전을 포함합니다. 그러나 모든 작업이 스레드로부터 안전하더라도 검색 작업은 잠금을 수반하지 않으며 모든 액세스를 차단하는 방식으로 전체 테이블을 잠그는 지원은 없습니다. 이 클래스는 스레드의 안전성에 의존하지만 동기화 세부 사항에는 의존하지 않는 프로그램에서 Hashtable과 완벽하게 상호 운용됩니다.

일반적으로 검색 작업 (get 포함)은 차단되지 않으므로 업데이트 작업 (넣기 및 제거 포함)과 겹칠 수 있습니다. 검색은 가장 최근에 완료된 업데이트 작업의 결과를 반영합니다. 지정된 열쇠의 갱신 조작은, 갱신 된 값을보고하는 그 열쇠에 대한 임의의 (null 이외의) 검색과의 발생 전 관계를 보관 유지합니다. putAll 및 클리어 등의 집계 조작에서는, 병행 취득이 삽입 또는 삭제를 반영하는 경우가 있습니다 일부 항목 만 표시합니다. 마찬가지로 Iterator, Spliterators 및 Enumerations는 반복자/열거 형을 만들 때 또는 생성 한 시점에서 해시 테이블의 상태를 반영하는 요소를 반환합니다. 그들은 ConcurrentModificationException을 throw하지 않습니다. 그러나 이터레이터는 한 번에 하나의 스레드에서만 사용하도록 설계되었습니다. size, isEmpty 및 containsValue를 포함한 집계 상태 메서드의 결과는 일반적으로지도가 다른 스레드에서 동시 업데이트를 수행하지 않는 경우에만 유용합니다. 그렇지 않으면 이러한 방법의 결과는 모니터링이나 추정 목적에는 적합하지만 프로그램 제어에는 적합하지 않을 수있는 과도 상태를 반영합니다. 여기

더 많은 정보는 : https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html

이 programmaticaly 정확히 고전 해시 맵처럼 동작합니다.

1

일반적인 방법은 구현하기 쉽지 않으며 많은 노력이 필요하며 여전히 어려운 일이 될 것입니다. Gomoku7에서 제안한대로 ConcurrentHashMap이 가장 좋습니다.

일반 접근 방식은 잠금을 기반으로 구현해야합니다. 업데이트하기 전에 객체를 잠그고 나중에 잠금을 해제해야합니다. 자바에는 types of locks이 다릅니다. 그래서, 당신의 필요에 맞는 자물쇠를 선택했습니다.

  1. Final

    이 당신의 친구입니다이 필요한 경우가 아니면
  2. 피가 임시 변수
  3. 사용 ExecutorsFork/Join
를 생성 가능한 객체에게 final을, 개체 변이하지 않는 : 몇 가지 팁이있다
관련 문제