volatile 원리 와 기교

volatile, 동기 화 대신 더 낮은 대가 로
왜 volatile 을 사용 하 는 것 이 동기 화 대가 보다 더 낮 습 니까? 동기 화의 대 가 는 주로 덮어 쓰기 범위 에 의 해 결정 되 며, 동기 화 덮어 쓰기 범 위 를 낮 출 수 있다 면 프로그램의 성능 을 대폭 향상 시 킬 수 있다.
volatile 의 커버 범 위 는 변수 단계 에 불과 하기 때문에 동기 화 대가 가 매우 낮다.
volatile 원 리 는 무엇 입 니까?volatile 의 의 미 는 프로세서 에 저 를 작업 메모리 에 넣 지 말 라 는 것 입 니 다. 메 인 메모리 에서 저 를 직접 조작 하 십시오. (작업 메모리 상세 내용 은 자바 메모리 모델 참조)
따라서 다 핵 또는 다 중 스 레 드 가 이 변 수 를 방문 할 때 메 인 저장 소 를 직접 조작 합 니 다. 이것 은 본질 적 으로 변수 공 유 를 실현 합 니 다.
volatile 의 장점 은 무엇 입 니까? 1. 더 큰 프로그램 스루풋 2. 더 적은 코드 는 다 중 스 레 드 3 을 실현 하고 프로그램의 신축성 이 비교적 좋 으 며 4. 이해 하기 쉬 우 며 너무 높 은 학습 비용 이 필요 없다.
volatile 은 어떤 열세 가 있 습 니까? 1. 문제 가 생기 기 쉬 워 요.
volatile 연산 에 더러 운 데이터 문제 가 존재 합 니 다.
volatile 은 변수의 가시 성 만 확보 할 수 있 을 뿐 원자 성 을 보장 할 수 없다.
volatile 의 race condition 예제:
public class TestRaceCondition {
    private volatile int i = 0;
 
    public void increase() {
       i++;
    }
 
    public int getValue() {
       return i;
    }
}

다 중 스 레 드 가 increase 방법 을 실행 할 때 그 값 이 선형 으로 증가 할 것 이 라 고 보장 할 수 있 습 니까? 답 은 부정 적 이다.
원인: 여기 increase 방법 은 i + +, 즉 i = i + 1 입 니 다.i = i + 1 에 대하 여 다 중 스 레 드 에서 의 연산 자 체 는 i 의 값 을 바 꿔 야 합 니 다. 만약 i 가 메모리 에서 최신 값 을 가 져 왔 으 나 1 과 연산 하지 않 았 다 면 다른 스 레 드 는 연산 결 과 를 i 에 게 수 차례 할당 하 였 으 며, 현재 스 레 드 가 끝 났 을 때 이전의 수 차례 연산 결 과 는 모두 덮어 씁 니 다.
즉, 100 회 increase 를 실행 하면 결 과 는 < 100. 일반적으로 이런 상황 은 비교적 높 은 압력 과 병발 상황 에서 만 나타 날 수 있 습 니 다.
어떻게 이런 상황 을 피 합 니까? 상기 문 제 를 해결 하 는 방법: 하 나 는 조작 할 때 동기 화 하 는 것 이다. 이런 방법 은 프로그램의 성능 을 크게 떨 어 뜨리 고 volatile 의 취지 에 어 긋 날 것 이다.
두 번 째 방식 은 하드웨어 원 어 (CAS) 를 사용 하여 비 차단 알고리즘 이 CPU 원 어 에서 변수 등급 의 저 소비 동기 화 를 지원 하 는 것 이다.
CPU 원 어 - 비교 및 교환 (CompareAndSet), 비 차단 알고리즘 구현
CAS 가 뭐 예요? 카 스 는 현대 CPU 가 병렬 프로그램 에 제공 하 는 원 어 동작 입 니 다. 서로 다른 CPU 는 서로 다른 사용 규범 을 가지 고 있 습 니 다.
Intel 프로세서 에서 명령 을 통 해 cmpxchg 시 리 즈 를 비교 하고 교환 합 니 다.PowerPC 프로세서 에는 '불 러 오기 및 보존' 과 '조건 저장' 이라는 명령 이 있 습 니 다. 같은 항목 을 실현 합 니 다.MIPS 는 첫 번 째 명령 을 제외 하고 PowerPC 프로세서 와 비슷 합 니 다.
CAS 작업 은 메모리 위치 (V), 예상 원 치 (A) 와 새 값 (B) 을 포함 합 니 다.
무엇이 비 차단 알고리즘 입 니까? 하나의 스 레 드 가 실패 하거나 걸 려 서 다른 스 레 드 의 실패 나 걸 려 서 는 안 됩 니 다. 이러한 알고리즘 을 비 차단 (nonblocking) 알고리즘 이 라 고 합 니 다.
대비 차단 알고리즘: 만약 에 하나의 병행 작업 이 있 으 면 그 중의 한 스 레 드 는 대상 모니터 의 자 물 쇠 를 우선 받 고 다른 스 레 드 가 동기 화 경계 에 도 착 했 을 때 차단 된다. 앞의 스 레 드 가 자 물 쇠 를 풀 어야 경쟁 대상 자 물 쇠 를 계속 할 수 있다. (물론 이곳 의 경쟁 도 공평 하 다. 선착순)
CAS 원리:
위치 V 는 값 A 를 포함해 야 한다 고 생각 합 니 다.이 값 을 포함 하면 B 를 이 위치 에 놓 습 니 다.그렇지 않 으 면 이 위 치 를 바 꾸 지 말고 이 위치의 현재 값 만 알려 주시 면 됩 니 다.
CAS 사용 예시 (jdk 1.5 및 패키지 AtomicInteger 류 분석:)
/**
    * Atomically sets to the given value and returns the old value.
    *
    * @param newValue the new value
    * @return the previous value
    */
   public final int getAndSet(int newValue) {
       for (;;) {
           int current = get();
           if (compareAndSet(current, newValue))
               return current;
       }
   }
 
   public final boolean compareAndSet(int expect, int update) {
       return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
   }

이 방법 은 AtomicInteger 류 의 일반적인 방법 입 니 다. 변 수 를 지정 한 값 으로 설정 하고 설정 전의 값 을 되 돌려 주 는 역할 을 합 니 다. cpu 원 어 compare AndSet 을 이용 하여 값 의 유일 성 을 보장 합 니 다.
또한, AtomicInteger 류 에서 다른 실 용적 인 방법 도 같은 실현 방식 을 바탕 으로 한다. 예 를 들 어 getAndIncrement, getAndDecrement, getAndAdd 등 이다.
CAS 의미 에 존재 하 는 'ABA 문제'.
ABA 문제 가 뭐 예요?V 주소 의 A 값 을 처음 읽 은 다음 CAS 를 통 해 V 주소 의 값 이 여전히 A 인지 여 부 를 판단 한다 고 가정 하고, 그렇다면 B 의 값 을 V 주소 에 기록 하고 A 값 을 덮어 씁 니 다.
그러나 의미 에 구멍 이 하나 있 습 니 다. V 의 A 값 을 처음 읽 었 을 때 메모리 V 의 값 은 B 값 으로 변 한 다음 CAS 를 실행 하지 않 기 전에 A 값 으로 변 했 습 니 다. 이때 CAS 가 다시 실 행 될 때 정확 한 것 을 판단 하고 값 을 부여 합 니 다.
이러한 판단 치 방식 은 메모리 가 수정 되 었 는 지 여 부 를 단정 하 는데, 어떤 문제 에 대해 서 는 적용 되 지 않 는 다.
이러한 문 제 를 해결 하기 위해 jdk 1.5 는 AtomicStamped Reference (표 시 된 원자 참조) 류 를 제공 하고 변수 값 을 제어 하 는 버 전 을 통 해 CAS 의 정확성 을 확보 합 니 다.
사실 대부분의 값 변 화 를 통 해 CAS 는 이미 충분 하 다.
jdk 1.5 원자 패키지 소개 (volatile 기반)
가방 의 특색: 1. 일반 원자 수치 유형 AtomicInteger, AtomicLong 은 원자 작업 의 가감 연산 을 제공 합 니 다.
2. 더러 운 데이터 문 제 를 해결 하 는 전형 적 인 모델 - '비교 후 설정' 을 사용 합 니 다. 즉, 메 인 저장 소 에 있 는 데이터 가 예상 한 값 과 일치 하 는 지 확인 하고 일치 하면 업데이트 합 니 다.
3. AtomicReference 를 사용 하면 모든 대상 에 대한 원자 참조 와 할당 을 실현 할 수 있 습 니 다. Double 과 Float 를 포함 하지만 이에 대한 계산 은 포함 되 지 않 습 니 다. 부동 소수점 계산 은 동기 키워드 나 Lock 인터페이스 에 의 해 만 이 루어 집 니 다.
4. 배열 요소 의 대상 에 대해 상기 특징 에 부합 되 는 경우 에 도 원자 조작 을 사용 할 수 있 습 니 다. 가방 에는 일부 배열 의 원자 조작 류 Atomic Integer Array, Atomic LongArray 등 이 제공 되 었 습 니 다.
5. 시스템 의 스루풋 과 성능 을 대폭 향상 시킨다.
구체 적 으로 사용, 자바 doc 를 자세히 설명 합 니 다.
저자: Ken Wu 링크: http://kenwublog.com/the-theory-of-volatile

좋은 웹페이지 즐겨찾기