[자바 병발 - 11] 병발 용기 사용

6823 단어 자바병발 하 다
자바 와 가방 의 상당 부분 은 에 관 한 것 이기 때문에 이 부분의 내용 을 배우 고 이해 하 는 것 이 필요 하 다.
자바 1.5 이전에 제 공 된 도 스 레 드 의 안전 을 보장 할 수 있 지만 성능 이 매우 떨 어 졌 고 자바 1.5 버 전 이후 제 공 된 병발 용 기 는 성능 에 있어 많은 최적화 되 었 으 며 용기 의 유형 도 더욱 풍부 해 졌 다.다음은 이 부분의 내용 을 비교 해 보 자.
동기 용기 및 주의사항
자바 의 용 기 는 주로 List, Map, Set, Queue 등 네 가지 로 나 눌 수 있 지만 모든 자바 용기 가 스 레 드 가 안전 한 것 은 아니다.예 를 들 어 우리 가 자주 사용 하 는 Array List, HashMap 은 스 레 드 가 안전 하지 않 습 니 다.스 레 드 안전 용 기 를 소개 하기 전에 우 리 는 먼저 이런 문 제 를 생각 합 니 다. 어떻게 비 스 레 드 안전 용 기 를 스 레 드 안전 용기 로 바 꿉 니까?
이전에 우 리 는 비 스 레 드 안전 용 기 를 대상 내부 에 밀봉 한 후에 방문 경 로 를 잘 제어 하면 된다 고 토론 했다.
다음은 Array List 를 예 로 들 어 스 레 드 안전 으로 만 드 는 방법 을 살 펴 보 겠 습 니 다.아래 코드 에서 SafeArrayList 내부 에 ArrayList 의 인 스 턴 스 c 가 있 습 니 다. 모든 방문 c 방법 은 synchronized 키 워드 를 추 가 했 습 니 다. 주의해 야 할 것 은 addIfNotExist () 방법 도 synchronized 로 원자 성 을 확보 하 는 것 입 니 다.
SafeArrayList{
  //    ArrayList
  List c = new ArrayList<>();
  //       
  synchronized
  T get(int idx){
    return c.get(idx);
  }

  synchronized
  void add(int idx, T t) {
    c.add(idx, t);
  }

  synchronized
  boolean addIfNotExist(T t){
    if(!c.contains(t)) {
      c.add(t);
      return true;
    }
    return false;
  }
}


여 기 를 보면 하 나 를 보면 열 을 거꾸로 들 고 모든 비 스 레 드 안전 류 는 이런 포장 방식 으로 스 레 드 안전 을 실현 할 수 있 지 않 을 까? 라 고 생각 할 수 있 습 니 다.사실은 자바 SDK 에서 이런 기능 을 제 공 했 고 Collections 라 는 클래스 에서 완 비 된 포장 클래스 를 제공 했다. 예 를 들 어 아래 의 예시 코드 에서 각각 Array List, HashSet 과 HashMap 을 라인 이 안전 한 List, Set 과 Map 으로 포장 했다.
List list = Collections.
  synchronizedList(new ArrayList());
Set set = Collections.
  synchronizedSet(new HashSet());
Map map = Collections.
  synchronizedMap(new HashMap());


앞서 말 한 , 예 를 들 어 위 에서 언급 한 addIfNotExist () 방법 은 조합 작업 을 포함한다.조합 조작 은 흔히 경쟁 조건 문 제 를 숨 기 고 모든 조작 이 원자 성 을 보장 할 수 있 더 라 도 조합 작업 의 원자 성 을 보장 할 수 없 으 므 로 이것 은 반드시 주의해 야 한다.
용기 분야 “ ” , 예 를 들 어 아래 코드 에서 교체 기 를 통 해 용기 list 를 옮 겨 다 니 며 모든 요소 에 foo () 방법 을 호출 하면 병발 문제 가 존재 합 니 다. 이러한 조합의 조작 은 원자 성 을 갖 추 지 못 합 니 다.
List list = Collections.
  synchronizedList(new ArrayList());
Iterator i = list.iterator(); 
while (i.hasNext())
  foo(i.next());


올 바른 방법 은 다음 과 같 습 니 다. list 를 잠 근 후에 옮 겨 다 니 는 작업 을 수행 하기 때문에 list 를 잠 그 는 것 은 스 레 드 가 안전 합 니 다.
List list = Collections.
  synchronizedList(new ArrayList());
synchronized (list) {  
  Iterator i = list.iterator(); 
  while (i.hasNext())
    foo(i.next());
}    


위 에서 언급 한 이러한 포장 을 거 친 후 라인 안전 용 기 는 모두 synchronized 라 는 동기 화 키 워드 를 바탕 으로 이 루어 진 것 이기 때문에 라 고도 부른다.자바 가 제공 하 는 동기 화 용 기 는 Vector, Stack, Hashtable 도 있 습 니 다. 이 세 용 기 는 포장 류 를 바탕 으로 이 루어 진 것 이 아니 라 synchronized 를 바탕 으로 이 루어 진 것 입 니 다. 이 세 용 기 를 옮 겨 다 니 며 자 물 쇠 를 채 워 서 서로 배척 해 야 합 니 다.
병발 용기 및 주의사항
자바 가 1.5 버 전에 서 이른바 스 레 드 안전 용 기 를 말 하 는데 주로 를 말 합 니 다. 물론 모든 방법 이 synchronized 로 상호 배척 을 보장 하기 때문에 직렬 도가 너무 높 고 성능 이 너무 떨 어 집 니 다.따라서 자바 는 1.5 및 그 후 버 전에 서 성능 이 더 높 은 용 기 를 제공 하 였 으 며, 우 리 는 일반적으로 라 고 부른다.
병발 용 기 는 수량 이 매우 많 지만 앞에서 우리 가 언급 한 네 가지 유형: List, Map, Set 과 Queue 이다.
병렬 용기 관계 도
여 기 는 단지 관건 을 소개 할 뿐이다.
(1) 리스트
리스트 에 하나 밖 에 없 는 실현 류 는 CopyOnWriteArrayList 이다.CopyOnWrite 는 말 그대로 쓸 때 공유 변 수 를 새로 복사 하 는 것 입 니 다. 읽 기 동작 이 전혀 잠 겨 있 지 않 은 것 이 좋 습 니 다.
CopyonWriteArray List 내부 에서 하나의 배열 을 유지 하고 있 습 니 다. 구성원 변수 array 는 이 내부 배열 을 가리 키 고 있 습 니 다. 모든 읽 기 동작 은 array 를 기반 으로 합 니 다. 다음 그림 에서 보 듯 이 교체 기 Iterator 가 옮 겨 다 니 는 것 은 array 배열 입 니 다.
반복 되 는 내부 구조 도 를 실행 하 다.
array 를 옮 겨 다 니 는 동시에 요 소 를 추가 하 는 등 쓰기 동작 도 있 습 니 다.CopyonWriteArray List 는 array 를 복사 한 다음 에 새로 복사 처 리 된 배열 에서 요 소 를 추가 하 는 작업 을 수행 하고 실행 한 후에 array 를 이 새로운 배열 로 가 리 킵 니 다.다음 그림 을 통 해 알 수 있 듯 이 읽 기와 쓰 기 는 병행 할 수 있 습 니 다. 옮 겨 다 니 는 작업 은 원래 array 를 기반 으로 실 행 됩 니 다. 쓰기 작업 은 새로운 array 를 기반 으로 합 니 다.
추가 요소 의 내부 구조 도 를 실행 합 니 다.
CopyonWriteArrayList 를 사용 할 때 주의해 야 할 '구덩이' 는 주로 두 가지 측면 이 있다.하 나 는 응용 장면 입 니 다. CopyOn Write Array List 는 쓰기 동작 이 매우 적은 장면 에 만 적용 되 고 읽 기와 쓰기 의 짧 은 불 일 치 를 용인 할 수 있 습 니 다.예 를 들 어 위의 예 에서 기 록 된 새로운 요 소 는 바로 옮 겨 다 닐 수 없습니다.또 다른 주의해 야 할 것 은 CopyOn Write Array List 교체 기 는 읽 기만 하고 삭제 수정 은 지원 되 지 않 습 니 다.교체 기 가 옮 겨 다 니 는 것 은 스냅 샷 일 뿐 스냅 샷 을 추가 삭제 하 는 것 은 무의미 하기 때문이다.
(2) 지도
Map 인터페이스의 두 가지 실현 은 Concurrent HashMap 과 Concurrent SkipListMap 이다. 이들 은 응용 측면 에서 볼 때 주요 한 차이 점 은 ConcurrentHashMap key , ConcurrentSkipListMap key 이다.그래서 키 의 순 서 를 보증 할 필요 가 있다 면 Concurrent SkipListMap 만 사용 할 수 있 습 니 다.
Concurrent HashMap 과 Concurrent SkipListMap 을 사용 할 때 주의해 야 할 점 은 키 와 value 가 비어 있 으 면 안 된다 는 것 입 니 다. 그렇지 않 으 면 NullPointerException 이 실행 중 이상 을 던 집 니 다.아래 표 는 Map 과 관련 된 실현 류 가 key 와 value 에 대한 요 구 를 정리 했다.
Concurrent SkipListMap 의 SkipList 자체 가 데이터 구조 이 고 중국 어 는 보통 '점프 표' 로 번역 된다.탭 삽입, 삭제, 조회 작업 의 평균 시간 복잡 도 는 O (log n) 로 이론 적 으로 동시 다발 스 레 드 수 와 관계 가 없 기 때문에 동시 다발 도가 매우 높 은 상황 에서 Concurrent HashMap 의 성능 에 만족 하지 않 으 면 ConcurrentSkipListMap 을 시도 해 보 세 요.
(3) 세트
Set 인터페이스의 두 가지 실현 은 CopyOn Write Array Set 과 Concurrent SkipList Set 입 니 다. 장면 을 사용 하면 앞에서 말 한 CopyOn Write Array List 와 Concurrent SkipList Map 을 참고 할 수 있 습 니 다. 그들의 원 리 는 모두 같 습 니 다. 여 기 는 더 이상 군말 하지 않 겠 습 니 다.
(4) 큐
자바 와 가방 안에 Queue 와 같은 병발 용 기 는 가장 복잡 합 니 다. 다음 두 가지 차원 에서 분류 할 수 있 습 니 다.하나의 차원 은 입 니 다. 차단 이란 대기 열 이 가득 찼 을 때 입대 작업 이 막 히 는 것 을 말 합 니 다.대기 열 이 비 었 을 때, 대기 열 동작 이 막 혔 습 니 다.또 다른 차원 은 인 데 한쪽 끝 은 팀 의 꼬리 만 팀 에 들 어 갈 수 있 고 팀 의 첫 번 째 팀 이 팀 에 나 가 는 것 을 말한다.양 끝 은 팀 의 첫 번 째 팀 과 끝 이 모두 팀 에 들 어 갈 수 있다 는 것 을 말한다.자바 및 가방 에 Blocking , Queue , Deque .
이 두 차원 을 조합 한 후에 Queue 를 네 가지 유형 으로 나 눌 수 있 습 니 다. 각각:
1. 단일 차단 대기 열
: 사실 현재 Array BlockingQueue, LinkedBlockingQueue, SynchronousQueue, LinkedTransfer Queue, Priority BlockingQueue 와 Delay Queue 가 있 습 니 다.내부 에 보통 하나의 대기 열 을 가지 고 있 습 니 다. 이 대기 열 은 배열 일 수도 있 고 링크 일 수도 있 습 니 다.심지어 대기 열 (SynchronousQueue) 을 가지 고 있 지 않 을 수도 있 습 니 다. 이때 생산자 스 레 드 의 가입 작업 은 소비자 스 레 드 의 출하 작업 을 기 다 려 야 합 니 다.한편, LinkedTransfer Queue 는 LinkedBlockingQueue 와 SynchronousQueue 의 기능 을 융합 시 켜 LinkedBlockingQueue 보다 성능 이 좋 습 니 다.Priority BlockingQueue 는 우선 순위 에 따라 팀 을 나 가 는 것 을 지원 합 니 다.Delay Queue 는 지연 출전 을 지원 합 니 다.
2. 양 끝 차단 대기 열
: 그 실현 은 링크 드 Blocking Deque 입 니 다.
3. 단일 비 차단 대기 열
: 그 실현 은 Concurrent LinkedQueue 입 니 다.
4. 양 끝 비 차단 대기 열
: 그 실현 은 Concurrent Linked Deque 입 니 다.
또한 대기 열 을 사용 할 때 대기 열 이 유 계 를 지원 하 는 지 각별히 주의해 야 합 니 다.실제 작업 에 서 는 무 계 대기 열 을 사용 하 는 것 을 권장 하지 않 습 니 다. 데이터 양 이 많 으 면 OOM 이 발생 하기 쉽 기 때 문 입 니 다.위 에서 언급 한 이 Queue 들 중 Array BlockingQueue 와 LinkedBlockingQueue 만 이 경계 가 있 기 때문에 , OOM

좋은 웹페이지 즐겨찾기