자바 에서 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 가상 컴퓨터 스 택 입 니 다.모든 스 레 드 가 실 행 될 때 하나의 스 레 드 스 택 이 있 고 스 레 드 스 택 은 스 레 드 가 실 행 될 때 변수 값 정 보 를 저장 합 니 다.스 레 드 가 특정한 대상 에 접근 할 때 값 은 먼저 대상 의 인용 을 통 해 메모리 에 해당 하 는 변수의 값 을 찾 은 다음 에 메모리 변수의 구체 적 인 값 을 스 레 드 로 컬 메모리 에 로드 하여 변수 사본 을 만 든 다음 에 스 레 드 는 대상 이 쌓 여 있 는 변수 값 과 아무런 관계 가 없 으 며 사본 변수의 값 을 직접 수정 합 니 다.수정 이 끝 난 후 어느 순간(스 레 드 가 종료 되 기 전에)스 레 드 변수 사본 의 값 을 대상 이 쌓 여 있 는 변수 에 자동 으로 기록 합 니 다.이렇게 쌓 여 있 는 대상 의 값 이 변 한다.아래 그림
대화 식 설명
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 키워드 로 수정 한 후에 도 동시 다발 적 인 상황 이 발생 할 수 있 습 니 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.