자바 병렬 튜 토리 얼 의 volatile 키워드 상세 설명

머리말
다 선정 에 대해 말하자면,나 는 우리 가 가장 중요 한 것 은 임계 구 개념 을 이해 하 는 것 이 라 고 생각한다.

예 를 들 어 한 반 에 한 여자 아이(임계 구역),49 명의 남자 아이(스 레 드)가 있 는데 남자 아이의 목 표 는 바로 이 여자 아이 이다.바로 경쟁 관계(스 레 드 안전 문제)가 있 을 것 이다.실제 장면 에 보급 한다.예 를 들 어 한 개의 수 를 더 하거나 감소 하 는 등 상황 은 조작 대상 이 하나 밖 에 없 기 때문에 다 중 스 레 드 환경 에서 스 레 드 안전 문제 가 발생 할 수 있다.임계 구역 의 개념 을 이해 하면 우 리 는 다 중 스 레 드 문제 에 대해 좋 은 의식 을 가 질 수 있다.
Jav 메모리 모델(JMM)
다 중 스 레 드 에 대해 서 는 자바 메모리 모델(JMM)의 추상 적 인 설명도 에 대해 알 아야 합 니 다.다음 그림:

스 레 드 A 와 스 레 드 B 가 실 행 될 때 공유 변수(임계 구역)를 읽 고 각각 로 컬 메모리 로 복사 하여 후속 작업 을 수행 합 니 다.
JMM 모델 은 자바 의 인터페이스 와 같은 규범 이다.JMM 은 원자 성,가시 성,질서 성 등 세 가지 문제 와 관련된다.
원자 성 이란한 스 레 드 의 실행 이 다른 스 레 드 에 영향 을 받 지 않 을 까 하 는 것 이다.그 는 중단 할 수 없다.예 를 들 어:

int i=1
이 문 구 는 Jmm 에서 원자 적 이다.하나의 스 레 드 가 실행 되 든 여러 스 레 드 가 이 문 구 를 실행 하 든 읽 은 i 는 1 과 같다.그것 은 무엇이 비 원자 성 입 니까?이치 에 따 르 면 자바 의 코드 가 모두 원자 성 이 라면 스 레 드 문제 가 없 을 것 입 니 다.사실 JMM.비원 자 적 예 를 들다.

i ++;
이 조작 은 원자 적 인 것 이 아니다.그 는 세 가지 조작 을 포함 하고 있 기 때문이다.첫 번 째 는 i 의 값 을 읽 고,두 번 째 는 i 에 1 을 더 하고,세 번 째 는 결 과 를 i 에 게 부여 하고,i 의 값 을 업데이트 하기 때문이다.
가시 성 이란하나의 값 이 스 레 드 A 에서 수정 되면 스 레 드 B 는 바로 이 결 과 를 알 게 될 것 임 을 나타 낸다.
질서 성 이란질서 성 값 이란 의미 의 질서 성 이다.코드 순서 가 바 뀔 수 있다 는 얘 기다.명령 재배 치 메커니즘 이 있 기 때문이다.명령 정렬 이란 cpu 의 실행 효율 을 높이 기 위해 코드 실행 순 서 를 바 꿉 니 다.재 정렬 오 류 를 방지 하기 위해 JMM 에는 happen-before 규칙 이 있 습 니 다.이 규칙 은 그 문 구 를 앞 에 두 고 그 문 구 를 뒤에 두 는 것 을 제한 합 니 다.
Happen-before:
프로그램 순서 원칙:하나의 스 레 드 에서 의미 의 직렬 성 을 확보 합 니 다.
volatile 원칙:volatile 변수의 쓰 기 는 읽 기 전에 발생 합 니 다.
잠 금 규칙:잠 금 을 먼저 넣 고 잠 금 을 해제 합 니 다.
전달 성:a 가 b 보다 먼저,b 가 c 보다 먼저,a 는 반드시 c 보다 먼저
스 레 드 의 start 방법 은 그의 모든 조작 보다 앞 선다.
스 레 드 의 모든 작업 이 스 레 드 의 끝 보다 앞 선다.
대상 의 구조 함수 실행,종료 가 finalize()방법 보다 먼저 입 니 다.
volatile
본론 에 들 어가 면 volatile 은 변수(임계 구역)의 가시 성과 질서 성 을 확보 할 수 있 으 나 원자 성 을 보장 할 수 없다.예 를 들 어:

public class VolatileTest implements Runnable{
 private static VolatileTest volatileTest = new VolatileTest();
 private static volatile int i= 0;
 public static void main(String[] args) throws InterruptedException {
  for (int j = 0; j < 20; j++) {
   Thread a = new Thread(new VolatileTest());
   Thread b = new Thread(new VolatileTest());
   a.start();b.start();
   a.join();b.join();
   System.out.print(i+"&&");
  }

 }
 
 @Override
 public void run() {
  for (int j = 0; j < 1000; j++) {
   i++;
  }
 }

}

//     
// 2000&&4000&&5852&&7852&&9852&&11852&&13655&&15655&&17655&&19655&&21306  
//&&22566&&24566&&26189&&28189&&30189&&32189&&34189&&36189&&38089&&
결과 에 따 르 면 문제 가 있 습 니 다.i 는 volatile 키 워드 를 추 가 했 지만 volatile 키 워드 는 i+의 원자 성 을 보장 할 수 없습니다.
어떤 장면 이 volatile 키 워드 를 사용 하기에 적합 합 니까?
1.경량급 의'읽 기-쓰기 자물쇠'전략

private volatile int value;
public int getValue(){ return value;}
public synchronized void doubleValue(){ value = value*value; }
2.단일 모드(더 블 검사 잠 금 메커니즘

private volatile static Singleton instace; 
public static Singleton getInstance(){ //         ,       
 //   null   ,  volatile       ,     ,     
 if(instance == null){   
  synchronized(Singleton.class) { //     ,      
   //   null  ,              
   if(instance == null){  
    instance = new Singleton(); //      
   } 
  }   
 } 
 return instance;
레 퍼 런 스
《현대 운영 체제(제3 판)중국어 판》.
《실전 자바 고 병발 프로 그래 밍》.
《자바 병발 프로 그래 밍 의 예술》.
총결산
이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기