자바 병렬 프로 그래 밍 (3) 스 레 드 보안 클래스 에 새로운 원자 작업 추가
4150 단어 자바
만약 우리 가 안전 한 링크 를 원한 다 면, 그 는 원자의 '없 으 면 (Put - If - Absent)' 동작 을 제공 해 야 합 니 다. 동기 화 된 List 류 는 이미 대부분의 기능 을 실현 하 였 으 며, 우 리 는 그것 이 제공 하 는 contains 방법 과 add 방법 에 따라 구 조 를 실현 할 수 있 습 니 다.
이 원자 조작 을 실현 하 는 네 가지 방법 이 있 을 수 있다.
첫 번 째 방법 이자 가장 안전 한 방법 은 바로 원시 류 를 바 꾸 는 것 이다.
그러나 이것 은 일반적으로 할 수 없습니다. 클래스 의 원본 코드 에 접근 하거나 변경 할 수 없 기 때 문 입 니 다. 원본 클래스 를 바 꾸 려 면 코드 의 동기 화 전략 을 깊이 이해 해 야 합 니 다. 이렇게 추 가 된 기능 은 기 존의 디자인 과 일치 합 니 다. 새로운 방법 을 클래스 에 직접 추가 한다 고 가정 하면 동기 화 정책 을 실현 하 는 모든 코드 가 원본 파일 에 있 음 을 의미 합 니 다.더 쉽게 이해 하고 유지 할 수 있 습 니 다.
또 다른 방법 은 이러한 종 류 를 확장 (계승) 할 수 있 습 니 다. - 만약 원시 류 가 디자인 할 때 확장 성 을 고려 했다 면.
예 를 들 어, 우 리 는 BetterVector 를 설계 하여 Vector 를 확장 할 수 있 고, 새로운 방법 인 putIfAbsent 를 추가 할 수 있다.
public class BetterVector<E> extends Vector<E>{
public synchronized boolean putIfAbsent(E x){
boolean absent = !contains(x);
if(absent)add(x);
return absent;
}
}
확장 Vector 는 매우 easy 이지 만 모든 클래스 가 Vector 처럼 상 태 를 하위 클래스 에 공개 하 는 것 은 아니 기 때문에 이런 방법 을 사용 하기에 적합 하지 않다.
”확장 방법 이 비교적 취약 하 다. 주요 원인 은 동기 화 전략의 실현 이 여러 소스 파일 로 분리 되 었 기 때문이다. 바 텀 클래스 가 동기 화 전략 을 바 꾸 었 다 고 가정 하고 서로 다른 잠 금 을 바 꾸 어 상 태 를 보호 하면 하위 클래스 가 파 괴 될 것 이다.
세 번 째 방법 은 보조 류 를 사용 하여 client 잠 금 체 제 를 실현 합 니 다.
예 를 들 어 Collections. synchronized List 가 봉 인 된 Array List 는 앞의 두 가지 방법 이 모두 통 하지 않 습 니 다. 클 라 이언 트 코드 는 동기 화 패키지 공장 방법 에서 돌아 오 는 List 대상 의 유형 을 모 르 기 때 문 입 니 다. 이 때 client 잠 금 방식 으로 확장 코드 를 '보조 클래스' 에 넣 습 니 다.
그래서 우 리 는 아주 자 연 스 럽 게 ListHelper 보조 류 를 썼 다.
public class ListHelper<E>{
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public synchronized boolean putIfAbsent(E x){
boolean absent = !list.contains(x);
if(absent)
list.add(x);
return absent;
}
}
어떻게 보면 문제 가 없 지만, 매우 유감스럽게도 이런 방식 은 잘못된 것 이다.
putIfAbsent 는 synchronized 라 고 밝 혔 지만 ListHelper 에 자 물 쇠 를 채 웠 습 니 다. List 는 자신 이나 내부 대상 의 자 물 쇠 를 사용 합 니 다. ListHelper 는 동기 화 된 가상 을 가 져 왔 을 뿐 입 니 다.
Vector 와 동기 화 패키지 클래스 의 문서 에서 Vector 나 패키지 용기 내부 자 물 쇠 를 통 해 client 자 물 쇠 를 지원 합 니 다. 다음은 정확 한 client 자 물 쇠 를 제공 합 니 다.
public class ListHelper<E>{
public List<E> list = Collections.synchronizedList(new ArrayList<E>());
public boolean putIfAbsent(E x){
synchronized (list){
boolean absent = !list.contains(x);
if(absent)
list.add(x);
return absent;}
}
}
하나의 원자 조작 을 통 해 클래스 를 확장 하 는 것 은 취약 합 니 다. 클래스 의 잠 금 코드 를 여러 클래스 에 분포 하기 때 문 입 니 다. 그러나 클 라 이언 트 의 잠 금 코드 는 전혀 무관 한 다른 클래스 에 넣 기 때문에 더욱 취약 합 니 다.
네 번 째 방법 은 조합 (Composition) 방식 을 사용한다.
public class ImprovedList<T> implements List<T> {
public final List<T> list;
public ImprovedList(List<T> list) {
this.list = list;
}
public synchronized boolean putIfAbsent(T x) {
boolean absent = !list.contains(x);
if (absent)
list.add(x);
return absent;
}
//... List
}
Improved List 는 내 장 된 자 물 쇠 를 통 해 추가 자 물 쇠 를 추가 합 니 다. 바 텀 List 가 스 레 드 가 안전 한 지 에 관심 이 없습니다. List 가 스 레 드 가 안전 하지 않 거나 족쇄 방식 을 바 꾸 었 더 라 도 Improved 는 일치 하 는 잠 금 체 제 를 제공 하여 스 레 드 안전성 을 실현 합 니 다. 추가 동기 화 층 은 가 벼 운 성능 손실 을 초래 할 수 있 지만 시 뮬 레이 션 과 는 또 하나 가 있 습 니 다.대상 의 잠 금 정책 보 다 는 Improved List 가 더 건장 합 니 다. 사실 우 리 는 자바 모니터 모드 를 사용 하여 기 존 List 를 패키지 하고 클래스 에서 바 텀 List 를 가리 키 는 의외 의 인용 을 하지 않 으 면 스 레 드 안전성 을 확보 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Is Eclipse IDE dying?In 2014 the Eclipse IDE is the leading development environment for Java with a market share of approximately 65%. but ac...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.