자바 의 volatile 키워드 에 정통 하 다.

머리말
일부 오픈 소스 프레임 워 크 의 소스 코드 에 서 는 volatile 이라는 키 워드 를 자주 볼 수 있 으 며,최근 에는 특별히 volatile 키워드 의 사용 방법 을 배 웠 다.
volatile 키워드:여러 스 레 드 가 데 이 터 를 공유 할 때 메모리 에 있 는 데 이 터 를 볼 수 있 도록 합 니 다.synchronized 에 비해 비교적 가 벼 운 동기 화 전략 입 니 다.
단점:
1.volatile 은'상호 배척 성'을 갖 추 지 못 한다.
2.volatile 은 변수의'원자 성'을 보장 할 수 없다.
많은 자료 에서 volatile 키 워드 를 이렇게 소개 합 니 다.
volatile 은 경량급 synchronized 로 다 중 프로세서 개발 에서 공유 변수의'가시 성'을 확보 합 니 다.하나의 스 레 드 가 공유 변 수 를 수정 할 때 다른 스 레 드 는 이 수 정 된 값 을 읽 을 수 있다 는 뜻 이다.
글 이 잘 이해 되 지 않 으 니 예 를 들 어 이해 하 시 오.
1.예
우선 volatile 키 워드 를 사용 하지 않 은 예 를 보십시오.

package com.swnote.java;

/**
 * volatile    
 *
 * @author lzj
 * @date [2019-04-47]
 */
public class VolatileTest {

 private boolean flag;

 public static void main(String[] args) {
 VolatileTest test = new VolatileTest();
 test.test();
 }

 public void test() {
 new Thread(() -> {
  try {
  Thread.sleep(1000L);
  } catch (InterruptedException e) {
  e.printStackTrace();
  }
  flag = true;
 }).start();

 new Thread(() -> {
  while (true) {
  if (flag) {
   System.out.println("thread flag = " + flag);
  }
  }
 }).start();
 }
}
이 예 에서 flag 공유 변 수 를 정 의 했 습 니 다.test 방법 에서 두 개의 스 레 드 를 열 었 습 니 다.첫 번 째 스 레 드 는 1 초 를 기다 린 후에 공유 변수 flag 의 값 을 true 로 수정 하고 두 번 째 스 레 드 는 순환 을 통 해 flag 의 값 을 판단 합 니 다.flag 의 값 이 true 일 때 출력 내용 입 니 다.
이때 두 가지 추측 이 있다.
4.567917.실 행 된 후에 출력 내용 을 볼 수 있다.즉,두 번 째 스 레 드 는 첫 번 째 스 레 드 가 공유 변수 flag 에 대한 수정 을 감지 할 수 있다 는 것 을 의미한다4.567917.실 행 된 후에 작업 내용 이 없다 는 것 은 두 번 째 스 레 드 가 공유 변수 flag 에 대한 수정 을 감지 하지 못 한 다 는 것 을 의미한다그리고 실행 결 과 는:

작업 의 출력 내용 이 없습니다.이 경우 두 번 째 스 레 드 는 공유 변수 flag 에 대한 첫 번 째 스 레 드 의 수정 을 감지 할 수 없습니다.
flag 변수 에 volatile 키 워드 를 추가 하 는 예 를 수정 합 니 다.즉,:

private volatile boolean flag;
그리고 다시 실행 합 니 다.이 결 과 는 다음 과 같 습 니 다.

이때 내용 출력 이 있 습 니 다.volatile 키 워드 를 추가 한 후에 두 번 째 스 레 드 는 첫 번 째 스 레 드 가 공유 변수 flag 에 대한 수정 을 감지 할 수 있 습 니 다.이것 은 바로 상기 개념 에서 말 한 volatile 이 다 중 프로세서 개발 에서 공유 변수의'가시 성'을 확보 한 것 입 니 다.
2.원리
위의 예 를 통 해 volatile 이 다 중 프로세서 개발 에서 공유 변수의'가시 성'을 확보 했다 는 것 을 증명 했다.그것 은 어떻게 실 현 된 것 일 까?
이 럴 때 자바 의 메모리 모델 을 소개 해 야 합 니 다.먼저 다음 과 같은 설명 도 를 보 세 요.

자바 메모리 모델 은 다음 과 같 습 니 다:
공유 변 수 는 메 인 메모리 에 저 장 됩 니 다.모든 스 레 드 는 개인 로 컬 메모리 가 있 습 니 다.로 컬 메모리 에는 이 스 레 드 에 사 용 된 메 인 메모리 의 복사 본 이 저장 되 어 있 습 니 다.스 레 드 는 변수의 모든 작업 을 자신의 로 컬 메모리 에서 해 야 합 니 다.메 인 메모리 의 변 수 를 직접 읽 을 수 없습니다.
이 를 통 해 상기 사례 는 volatile 을 추가 하지 않 았 을 때 다음 과 같다.
첫 번 째 스 레 드 는 주 메모리 에서 공유 변수 flag 의 값 을 가 져 옵 니 다.이 값 은 false 입 니 다.이 값 을 로 컬 메모리 에 넣 고 변 수 를 수정 한 다음 에 값 을 true 로 바 꿉 니 다.이 때 는 로 컬 메모리 에 있 는 flag 의 값 을 true 로 바 꾸 었 을 뿐 이 때 는 주 메모리 에 같은 값 을 가 져 오지 않 았 습 니 다.그 다음 에 두 번 째 스 레 드 도 공유 변수 flag 의 값 을 자신의 로 컬 메모리 에 넣 었 습 니 다.이때 flag 의 값 은 false 이기 때문에 내용 출력 이 없 었 습 니 다.
그러나 volatile 키 워드 를 추가 하면 첫 번 째 스 레 드 가 flag 에 대한 수정 은 메 인 메모리 에 강제로 새로 고침 되 는 동시에 다른 스 레 드 의 로 컬 메모리 값 이 잘못 되 고 메 인 메모리 에 다시 가 져 와 야 합 니 다.그러면 첫 번 째 스 레 드 가 flag 를 수정 한 후에 두 번 째 스 레 드 가 감지 할 수 있 습 니 다.
3.조심 하 세 요
volatile 은 경량급 synchronized 이지 만 synchronized 를 대체 할 수 없습니다.volatile 은 원자 작업 의 안전 만 보장 할 수 있 기 때문에 복합 작업 에 있어 서 volatile 은 스 레 드 안전 을 보장 할 수 없습니다.
예 를 들 면:

package com.swnote.java;

/**
 *       
 *
 * @author lzj
 * @date [2019-04-27]
 */
public class StatisticTest {
 private volatile int num = 0;

 public static void main(String[] args) {
  StatisticTest test = new StatisticTest();
  test.statistic();
 }

 public void statistic() {
  for (int i = 0; i < 20; i++) {
   new Thread(() -> {
    num++;
   }).start();
  }

  System.out.println("num = " + num);
 }
}
기대 하 는 운행 결 과 는 20 이지 만 거의 매번 운행 결 과 는 다르다.예 를 들 어 어떤 결 과 는:

이것 은 num++이 조작 은 원자 성 이 아니 기 때문에 volatile 키 워드 를 사용 하 더 라 도 안전 을 보장 할 수 없습니다.
총결산
이상 은 이 글 의 모든 내용 입 니 다.본 고의 내용 이 여러분 의 학습 이나 업무 에 어느 정도 참고 학습 가 치 를 가지 기 를 바 랍 니 다.여러분 의 저희 에 대한 지지 에 감 사 드 립 니 다.

좋은 웹페이지 즐겨찾기