volatile 키워드 에서 동시 다발 문제 에 대한 개인 적 이해
5694 단어 volatile
먼저 volatile 의 의 미 를 상세 하 게 분석 한 글 을 살 펴 보 자.
http://www.infoq.com/cn/articles/java-memory-model-4
volatile 키워드 의 의 미 를 물 어보 면 다음 과 같은 답 을 얻 을 수 있다.
(1) volatile 에 대한 수식 변 수 는 각 스 레 드 간 의 쓰기 동작 이 다른 스 레 드 에 즉시 표 시 됩 니 다.
(2) volatile 수식 변수의 조작 은 원자 적 이 며, volatile 의 할당 작업 이 그의 이전 값 에 의존 하면 원자 성 을 잃 게 된다.
사실은 (1) 더욱 깊 은 의 미 를 가진다. 즉, 가시 성에 대한 이해 이다.(2) volatile 자체 와 원자 성 은 직접적인 관계 가 없다. (2) 에서 말 한 원자 성 은 사실 진정한 의미 의 원자 성 이 아니 라 가시 적 인 또 다른 표현 형식 이다.
그것 은 무엇이 가시 적 인 문제 입 니까? 같은 코드 에 대해 실행 라인 과 관찰 라인 이 보 이 는 실행 순서 가 반드시 일치 하 는 것 은 아 닙 니 다.듣 기 에 좀 까다롭다. 다음 과 같은 예 를 보 자.
난 서 집행 으로 인 한 가시 적 문제
다음 글 의 위조 코드 를 예 로 들 어 난 서 집행 으로 인 한 가시 적 인 문 제 를 설명 한다.
스 레 드 1:
Resource resource=init();
boolean hasInit=true;
afterOperation();
스 레 드 2:
if(hasInit){
getResource();
more operation;
}
위 프로그램 은 대충 보 더 라 도 스 레 드 2 에서 hasInit = true 일 때 resource 는 반드시 초기 화 되 었 습 니까? 답 은 부정 적 입 니 다.
JAVA 는 효율 성 을 위해 코드 가 실 행 될 때 어느 정도 명령 어 를 어 지 럽 히 지만 같은 스 레 드 내 프로그램 에 서 는 어 지 럽 습 니 다.
순서 실행 은 모든 코드 가 이전에 실 행 된 코드 에 영향 을 주지 않 습 니 다. 상기 프로그램 에 서 는 스 레 드 1 의 after Operation () 이 flag 값 을 true 로 가 져 왔 을 때 resource 는 초기 화 되 었 을 것 입 니 다. 그러나 스 레 드 2 에 서 는 resource 가 초기 화 되 지 않 았 을 때 true 인 flag 값 을 가 져 올 수 있 습 니 다.
이전 volatile 의 의미 로 돌아 가면 다음 과 같 습 니 다.
스 레 드 2 에 있어 서 스 레 드 1 의 after Operation () 은 스 레 드 2 에 의 해 관찰 되 었 습 니 다. flag 가 이미 true 일 까요? 답 은 부정 적 입 니 다. 구체 적 인 원인 은 volatile 의 메모리 의미 두 번 째 조 를 참고 하 십시오. 즉, volatile 의 읽 기 가 필요 합 니 다.
이상 은 글 의 첫머리 에서 말 하 는 "가시 성" 의 진정한 의미 입 니 다. 또한, 난 서 실행 은 컴 파일 된 명령 의 경우, JAVA 명령 한 마디 가 컴 파일 된 후의 실행 명령 도 난 서 에 의 해 실 행 될 수 있 습 니 다. 이 는 다음 에 언급 된 단일 모델 에서 설명 합 니 다.
참고 로 다 중 스 레 드 상황 에서 코드 의 가시 성 을 어떻게 신속하게 판단 합 니까? 실제 응용 에 서 는 happens - before 원칙 을 참고 할 수 있 습 니 다.
이상 은 사실 가시 적 인 문제 이다. 실제 응용 에서 가시 적 인 문 제 를 제외 하고 더욱 흔히 볼 수 있 는 것 은 원자 적 인 문제 이다.
원자 조작 이 파괴 되다
가장 간단 한 변수 부터 추가 작업 을 시작 합 니 다. JAVA 의 자체 증가 작업 은 원자 적 인 것 이 아니 라 는 것 은 잘 알려 져 있 습 니 다. JAVA 명령 한 마디 는 컴 파일 러 에 의 해 여러 명령 으로 분해 되 어 실 행 됩 니 다. 자체 증가 작업 의 경우, a++ 실행 중인 작업 의 바이트 번 호 는 다음 과 같 습 니 다.
public void getNext(); Code: 0: aload 0 / / 국부 변수 표 index 를 0 으로 불 러 오 는 변수 입 니 다. 여기 서 this 입 니 다. 1: dup //현재 스 택 의 대상 을 참조 하여 복사 합 니 다. 2: getfield #2; / Field id: I, id 의 값 을 가 져 오고 그 값 을 창고 꼭대기 에 눌 러 줍 니 다. 5: iconst_1 //int 형의 값 1 을 창고 꼭대기 에 눌 러 넣 기 6: iadd //스 택 꼭대기 두 int 형식의 요 소 를 더 하고 그 값 을 스 택 꼭대기 에 누 르 십시오. 7: putfield #2; / / Field id: I, 스 택 꼭대기 의 값 을 id 에 할당 합 니 다. 10: return }
만약 에 자체 증가 작업 을 수행 할 때 다른 스 레 드 가 같은 변수 a 에 대해 쓰기 작업 이나 읽 기 작업 을 하면 작업 대상 은 실행 과정 에서 상태 가 이상 한 변수 이 고 기대 밖의 결 과 를 얻 을 수 있 습 니 다.구체 적 인 자체 증가 작업 에 대한 다 중 스 레 드 테스트 는 인터넷 에 많다.
원자 적 개념 은 쉽게 말 하면 열 조작 을 할 때 작업 중의 동작 이 실행 되 지 않 거나 모두 실 행 된 후에 야 실행 결 과 를 다른 스 레 드 에 볼 수 있다 는 것 이다.
상기 개념 과 마찬가지 로 여러 개의 문 구 를 운송 할 수 있다. 예 를 들 어 한 방법 에서 다음 과 같은 write 작업 을 수행 해 야 한다.
boolean flag=true;
Date date=new Date();
이 두 변수의 상 태 는 함께 업데이트 해 야 합 니 다. flag = true 가 실 행 된 후에 바로 다른 스 레 드 에서 읽 히 면 다른 스 레 드 에서 잘못된 date 변 수 를 얻 을 수 있 습 니 다.즉, 앞에서 말 한 '실행 과정 에서 상태 가 이상 한 변수' 이다.
해결 방법 은 바로 상기 write 작업 과 read 작업 이 같은 자물쇠 로 synchronized 를 하 는 것 입 니 다.이렇게 하면 write 작업 을 할 때 정확 하지 않 은 값 이 다른 스 레 드 에서 읽 히 지 않 음 을 보증 할 수 있 습 니 다.
원자 성 문 제 는 때때로 가시 적 인 문제 와 동시에 나타 나 는데 전형 적 인 대 표 는 바로 유명한 이중 잠 금 을 바탕 으로 하 는 단일 모델 이다.
private Resource resource;
public static Resource getInstance(){
if( resource == null ){ //(1)
synchronized(lock){
if( resource == null ){
resource = new Resource(); //(4)
}
}
}
이 쓰기 의 resource 변 수 는 경쟁 자원 으로 4 로 표 시 된 문 구 는 실 패 를 일 으 킬 수 있 습 니 다.이 유 는 resource = new Resource () 라 는 말 에 최소 2 단계 가 포함 되 어 있 기 때 문 입 니 다. 하 나 는 resource 대상 의 구조 함 수 를 호출 하고 초기 화 하 는 것 입 니 다. 다른 하 나 는 새로 분 배 된 resource 대상 의 메모리 참조 할당 값 을 resource 변수 에 부여 하 는 것 입 니 다.다른 스 레 드 에서 문 구 를 실행 할 때 resource 를 volatile 로 설정 하지 않 았 기 때문에 비어 있 지 않 지만 초기 화 되 지 않 은 resource 대상 을 가 져 올 수 있 습 니 다.이것 이 바로 앞에서 말 한 난 서 집행 으로 인 한 문제 다.
요약:
병발 문 제 는 주로 자원 경쟁 시 원자 조작 이 파괴 되 고 다 중 스 레 드 상황 에서 무질서 하 게 집행 되 어 발생 하 는 스 레 드 가시 성 으로 나 뉜 다.
병발 과정 에서 상술 한 두 가지 문제 에 부 딪 히 면 모두 해결 방식 을 고려 해 야 한다.
흔히 볼 수 있 는 해결 방식 은 자 물 쇠 를 넣 어 실현 하 는 것 이다.자물쇠 의 획득 도 volatile 이 읽 는 메모리 의 미 를 가지 고 있 으 며, 자물쇠 의 방출 은 volatile 이 쓴 메모리 의 미 를 가지 고 있 습 니 다.만약 공력 이 부족 하 다 면, 다 중 스 레 드 프로 그래 밍 을 할 때 volatile 변 수 를 적 게 사용 하여 병발 문 제 를 해결한다.자 물 쇠 를 사용 하면 온당 하 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Java에서 volatile 키워드의 역할 및 사용법 상세 설명volatile 키워드의 역할은 시스템의 모든 라인이 이 키워드 수식에 대한 변수를 공유하고 볼 수 있도록 하는 것이다. 공유 변수가volatile로 수식될 때, 수정된 값이 메모리에 즉시 업데이트되고, 다른 라인이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.