자바 에서 volatile 키워드 의 역할 을 깊이 분석 하 다.

4379 단어 Javavolatile
자바 스 레 드 병행 처리 에서 하나의 키워드 volatile 의 사용 은 현재 매우 큰 혼동 이 존재 합 니 다.이 키 워드 를 사용 하면 다 중 스 레 드 병행 처 리 를 할 때 만사 가 다 잘 될 것 이 라 고 생각 합 니 다.
자바 언어 는 다 중 스 레 드 를 지원 합 니 다.스 레 드 병행 문 제 를 해결 하기 위해 언어 내부 에 동기 화 블록 과 volatile 키워드 체 제 를 도입 하 였 습 니 다.
synchronized 동기 화 블록 은 모두 가 잘 알 고 있 습 니 다.synchronized 키 워드 를 통 해 이 루어 집 니 다.synchronized 와 블록 문 구 를 더 하면 다 중 스 레 드 에 접근 할 때 같은 시간 에 하나의 스 레 드 만 synchronized 로 수식 할 수 있 는 방법 이나 코드 블록 이 있 습 니 다.
volatile 은 volatile 로 장 식 된 변 수 를 사용 합 니 다.스 레 드 는 변 수 를 사용 할 때마다 변 수 를 수정 한 후의 가장 큰 값 을 읽 습 니 다.volatile 은 원자 조작 을 하기 위해 오용 되 기 쉽다.
다음은 하나의 예 를 들 어 우 리 는 계수 기 를 실현 합 니 다.스 레 드 가 시 작 될 때마다 카운터 inc 방법 을 호출 하여 계수 기 를 추가 합 니 다.
실행 환경-jdk 버 전:jdk 1.6.031,메모리:3G   cpu:x86 2.4G

public class Counter {

    public static int count = 0;

    public static void inc() {

        // 1 ,
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }

        count++;
    }

    public static void main(String[] args) {

        // 1000 , i++ ,

        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Counter.inc();
                }
            }).start();
        }

        // , 1000
        System.out.println(" :Counter.count=" + Counter.count);
    }
}
운행 결과:Counter.count=995 실제 연산 결 과 는 매번 다 를 수 있 습 니 다.이 컴퓨터 의 결 과 는 다음 과 같 습 니 다.운행 결과:Counter.count=995.다 중 스 레 드 환경 에서 Counter.count 는 1000 여 명의 사람들 이 이것 이 다 중 스 레 드 병발 문제 라 고 생각 하지 않 습 니 다.변수 count 에 volatile 만 추가 하면 이 문 제 를 피 할 수 있 습 니 다.코드 를 수정 해서 결과 가 우리 의 기대 에 부합 되 는 지 확인 하 겠 습 니 다

public class Counter {

    public volatile static int count = 0;

    public static void inc() {

        // 1 ,
        try {
            Thread.sleep(1);
        } catch (InterruptedException e) {
        }

        count++;
    }

    public static void main(String[] args) {

        // 1000 , i++ ,

        for (int i = 0; i < 1000; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    Counter.inc();
                }
            }).start();
        }

        // , 1000
        System.out.println(" :Counter.count=" + Counter.count);
    }
}
실행 결과:Counter.count=992
운행 결 과 는 여전히 우리 가 기대 하 는 1000 이 없다.다음은 원인 을 분석 해 보 자.
자바 쓰레기 회수 정리 글 에서 jvm 실행 시간 메모리 의 분 배 를 묘사 하 였 습 니 다.그 중 하 나 는 jvm 가상 컴퓨터 스 택 입 니 다.모든 스 레 드 가 실 행 될 때 하나의 스 레 드 스 택 이 있 고 스 레 드 스 택 은 스 레 드 가 실 행 될 때 변수 값 정 보 를 저장 합 니 다.스 레 드 가 특정한 대상 에 접근 할 때 값 은 먼저 대상 의 인용 을 통 해 메모리 에 해당 하 는 변수의 값 을 찾 은 다음 에 메모리 변수의 구체 적 인 값 을 스 레 드 로 컬 메모리 에 로드 하여 변수 사본 을 만 든 다음 에 스 레 드 는 대상 이 쌓 여 있 는 변수 값 과 아무런 관계 가 없 으 며 사본 변수의 값 을 직접 수정 합 니 다.수정 이 끝 난 후 어느 순간(스 레 드 가 종료 되 기 전에)스 레 드 변수 사본 의 값 을 대상 이 쌓 여 있 는 변수 에 자동 으로 기록 합 니 다.이렇게 쌓 여 있 는 대상 의 값 이 변 한다.아래 그림
대화 식 설명
java volatile1
read and load 메 인 메모리 에서 변 수 를 현재 작업 메모리 use and assign 으로 복사 합 니 다.  실행 코드,공유 변수 값 store and write 를 변경 하여 작업 메모리 데이터 로 메 인 메모리 관련 내용 을 새로 고 칩 니 다.
그 중 use and assign 은 여러 번 나타 날 수 있 습 니 다.
그러나 이 작업 은 원자 성 이 아 닙 니 다.즉,readload 이후 에 메 인 메모리 count 변수 가 수정 되면 스 레 드 작업 메모리 의 값 이 불 러 와 서 대응 하 는 변화 가 없 기 때문에 계 산 된 결 과 는 예상 과 다 를 것 입 니 다.
volatile 수식 변수 에 대해 jvm 가상 머 신 은 메 인 메모리 에서 스 레 드 작업 메모리 로 불 러 오 는 값 이 최신 임 을 보증 합 니 다.
예 를 들 어 스 레 드 1,스 레 드 2 가 read,load 작업 을 하면 메 인 메모리 에 있 는 count 의 값 이 모두 5 인 것 을 발견 하면 이 최신 값 을 불 러 옵 니 다.
스 레 드 1 더미 count 를 수정 하면 주 메모리 에 write 되 고 주 메모리 의 count 변 수 는 6 으로 변 합 니 다.
스 레 드 2 는 read,load 작업 이 진행 되 었 기 때문에 연산 을 한 후에 도 메 인 메모리 count 의 변 수 를 6 으로 업데이트 합 니 다.
두 스 레 드 를 volatile 키워드 로 수정 한 후에 도 동시 다발 적 인 상황 이 발생 할 수 있 습 니 다.

좋은 웹페이지 즐겨찾기