자바 의 volatile 키워드 에 대한 정렬
4984 단어 Java
(1)가시 성
(2)명령 재 정렬 금지
첫 번 째 가시 성 은 이해 하기 쉽다.바로 volatile 로 장 식 된 공유 변 수 를 사용 하 는 것 이다.만약 에 한 라인 이 값 을 수정 하면 다른 라인 에서 바로 볼 수 있다.원 리 는 volatile 변수 에 대한 읽 기와 쓰기 입 니 다.주 메모리 에서 스 레 드 작업 을 강제 합 니 다.
제2 조 명령 을 다시 정렬 하 는 것 을 금지 하고 국부 적 인 코드 가 실행 되 는 순 서 를 확보 할 수 있다.만약 에 우리 가 지금 다음 과 같은 코드 가 있다 고 가정 하면:
int a=2;
int b=1;
순서 적 으로 a 는 먼저 실행 해 야 하고 b 는 나중에 실행 해 야 한다.그러나 실제 적 으로 꼭 그렇지 는 않다.cpu 가 프로그램 을 실행 할 때 연산 효율 을 높이 기 위해 모든 명령 은 동시 다발 적 인 난 서 집행 이다.만약 에 a 와 b 두 변수 사이 에 의존 관계 가 없다 면 b 가 먼저 실행 하고 a 가 나중에 실행 할 수 있다.의존 관계 가 존재 하지 않 기 때문이다.그래서 누가 먼저,누가 나중에 프로그램의 최종 결과 에 영향 을 주지 않 는 다.이른바 지령 재 정렬 이다.ok,이어서 우 리 는 다음 에 약간 변 경 된 코드 를 계속 분석 합 니 다.
int a=2;
int b=1;
int c=a+b;
이 코드 에서 a 와 b 가 어떻게 무질서 하 게 실행 되 든 c 의 결 과 는 3 이다.c 변 수 는 a 와 b 변수 에 의존 하기 때문에 c 변 수 는 a 나 b 로 정렬 되 기 전에 a 와 b 도 c 로 다시 배열 되 지 않 는 다.이것 은 happens-before 관계 의 단선 에서 as-if-serial 의 의미 에 의 해 제 한 된 것 이다.
이 안 에는 또 하나의 특수 한 상황 이 있 으 니 주의해 야 한다.
int a = 1;
int b = 2;
try {
a = 3; //A
b = 1 / 0; //B
} catch (Exception e) {
} finally {
System.out.println("a = " + a);
}
위의 예 에서 a 와 b 변 수 는 의존 관계 가 없 지만 try-catch 블록 에서 정렬 이 발생 했 습 니 다.b 가 먼저 실행 한 다음 에 이상 이 발생 했 습 니 다.그러면 a 의 값 은 결국 3 입 니 다.JVM 은 정렬 이 이상 할 때 catch 블록 에서 관련 된 특수 처 리 를 하도록 보장 합 니 다.이 점 은 주의해 야 한다.
단일 스 레 드 환경 에서 명령 재 정렬 은 프로그램의 최종 실행 결과 에 영향 을 주지 않 습 니 다.그러나 재 정렬 은 다 중 스 레 드 환경 에서 프로그램 이 정상적으로 실행 하 는 데 영향 을 줄 수 있 습 니 다.아래 의 코드 를 보 세 요.
public class ReorderDemo1 {
private int count=2;
private boolean flag=false;
private volatile boolean sync=false;
public void write1() {
count=10;
flag=true;// volatile , , flag=true
}
public void read1() {
if(flag){
System.out.print(count); // jvm 10, jvm 2,
}
}
public void write2() {
count=10;
sync=true;// volatile,
}
public void read2() {
if(sync){
System.out.print(count); // jdk5 , volatile ,count 10
}
}
public static void main(String[] args) {
for(int i=0;i<300;i++){
//
ReorderDemo1 reorderDemo1=new ReorderDemo1();
//
Thread t1=new Thread(()-> { reorderDemo1.write1();});
//
Thread t2=new Thread(()-> { reorderDemo1.read1(); });
t1.start();
t2.start();
}
}
}
위의 코드 에는 세 개의 구성원 변수 가 있 는데 그 중 마지막 하 나 는 volatile 로 장식 한 것 이 고 두 가지 방법 이 있 습 니 다.
첫 번 째 방법 중:
private int count=2;
private boolean flag=false;
private volatile boolean sync=false;
public void write1() {
count=10;
flag=true;// volatile , , flag=true
}
public void read1() {
if(flag){
System.out.print(count); // jvm 10, jvm 2,
}
}
위의 코드 는 명령 이 정렬 되 기 때문에 스 레 드 에서 write 1 방법 을 실행 하 는 flag=true 일 때 스 레 드 2 가 read 1 방법 을 실 행 했 습 니 다.그러면 count 의 값 은 확실 하지 않 습 니 다.10 일 수도 있 고 2 일 수도 있 습 니 다.이것 은 운영 체제 와 매우 큰 관계 가 있 습 니 다.예 를 들 어 cpu 가 명령 정렬 을 지원 하지 않 으 면 문제 가 발생 하지 않 습 니 다.예 를 들 어 X86 의 CPU 에서 코드 테스트 를 실행 하면 여러 개의 값 이 나타 나 지 않 을 수 있 지만 다른 운영 체제 도 나타 나 지 않 는 다 는 것 을 설명 할 수 없다.명령 재 정렬 은 다 중 스 레 드 환경 에서 불확실 성 을 가 져 올 수 있 습 니 다.정확하게 사용 하려 면 JMM 메모리 모델 을 이해 해 야 합 니 다.
두 번 째 방법 중:
private int count=2;
private boolean flag=false;
private volatile boolean sync=false;
public void write2() {
count=10;
sync=true;// volatile,
}
public void read2() {
if(sync){
System.out.print(count); // jdk5 , volatile ,count 10
}
}
여기 서 sync 변 수 는 volatile 수식 을 추가 한 것 으로 정렬 을 금지 한 다 는 뜻 입 니 다.첫 번 째 스 레 드 가 write 2 방법 을 호출 할 때 똑 같이 두 번 째 스 레 드 가 read 2 방법 을 호출 할 때 sync=true 라면 count 의 값 은 반드시 10 입 니 다.어떤 친구 들 은 count 변 수 는 volatile 로 수식 하지 않 았 다 고 말 할 수 있 습 니 다.100%가시 성 을 어떻게 보장 합 니까?확실히 jdk 5 이전에 volatile 키 워드 는 이러한 문제 가 존재 합 니 다.반드시 volatile 수식 을 해 야 합 니 다.그러나 jdk 5 와 그 후에 이 문 제 를 복 구 했 습 니 다.즉,jsr 133 에서 volatile 키 워드 를 강화 한 것 입 니 다.volatile 변수 자 체 는 하나의 울타리 로 볼 수 있 고 그 전후의 변수 도 volatile 의 미 를 가지 도록 보장 할 수 있 습 니 다.또한 volatile 의 등장 으로 정렬 이 금지 되 어 있 기 때문에 다 중 스 레 드 에서 도 정확 한 결 과 를 얻 을 수 있 습 니 다.
요약:
자바 에 서 는 volatile 을 제외 하고 정렬 을 금지 하 는 기능 이 있 으 며,내 장 된 잠 금 synchronized 와 가방 을 보 내 는 Lock 도 같은 의 미 를 가진다.동기 화 수단 으로 해결 하 는 주요 문 제 는 코드 집행 의 원자 성,질서 성,가시 성 을 확보 하 는 것 이다.내 장 된 자물쇠 와 J.U.C 의 자 물 쇠 는 이 세 가지 기능 을 동시에 가지 고 있 으 며,volatile 은 원자 성 을 보장 할 수 없 기 때문에 필요 할 때 자물쇠 와 함께 사용 해 야 정확 한 다 중 스 레 드 응용 을 만 들 수 있 습 니 다.
jsr 133 상세 소개:http://www.cs.umd.edu/~pugh/java/memoryModel/jsr-133-faq.html#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에 따라 라이센스가 부여됩니다.