코어 동시성 : 무엇 CAS인가? Java8는 CAS를 최적화하는 방법? 난 당신이 연주 이해하지 않는다

당신은 자바와 계약에 읽고 싶은 경우, Java 및 계약의 말을 들어있을 수 있습니다, 그 핵심은 첫째 메커니즘의 CAS를 이해하는 것입니다, CAS는 말했다 될 수 있기 때문에 기본이되는 구현 및 계약의 원칙.

오늘은 CAS가 원자 연산을 보장하는 방법을 이해뿐만 아니라, 내용과 CAS Java8 최적화 소요됩니다.

동기화 : 과잉

몇 줄의 코드에서 살펴 보자 :

public class CASTest {
    static int i = 0;

    public static void increment() {
        i++;
    }
}

100 개 스레드가있는 경우 동시에 내가 내가 증가 연산 결과가 될 것이다 (100)을 수행 할 수 증가 () 메서드를 호출?

알아 멀티 스레드 학생들이이 방법은 스레드로부터 안전하지 않습니다 것을, 내가 ++되지 않기 때문에 알아야 원자 조작 , 100를 얻을 어렵습니다.

(건너 뛸 수있는 알려진) 조금 (100)는, 내가이 작업을 ++가되지 않습니다 이유를 설명, 컴퓨터가 세 단계로 구분되어 수행 될 필요가있다.
1, i 값을 판독한다.
2, i가 1만큼 증가된다
(3), 최종 결과는 메모리 I에 기록된다. 스레드 A의 값을 읽으면 따라서 I I = 0, 또한 B 스레드 이번에는 0 = 1의 값을 판독한다. 다음 난 1로 증가하고, I = 1의 경우 다음에, 메모리에 기록. 그럼, 그때 메모리에 기록 스레드 B가 이때 메모리 나 1 = B, 그때 B가 I 인 스레드로 1 = 1 증가된다. 즉, 스레드 A, I는 사람 증가하고 있었다 B, 그러나 최종 결과는 1이 아닌 2이다.

그럼 어떻게 그것을 할까? 다음과 같이 해결 전략은 일반적으로,이 방법에 잠금 장치를 추가하는

public class CASTest {
    static int i = 0;

    public synchronized static void increment() {
        i++;
    }
}

동기화를 첨가 한 후, 당신은 단지 증가를 입력 할 수있는 하나 개의 스레드를 가질 수있다 () 메소드가 있습니다. 이 방법으로, 스레드 안전 표시되지 않습니다. 나는이 글을 볼 수 있습니다 동기화 이해가 안 : 철저하게 (헤비급 잠금 바이어스 잠금에서) 동기화 알아보기

그러나, 잠금 얻을 때이 방법을 증가 경쟁하기 위해 많은 스레드가 동기화 된 키워드의 추가 후 약간 과도 같은 느낌 동기화 동기화의 추가에 대한 간단한 증가 연산자,,, 됩니다 차단 하는 방법을, 마지막으로, 그들을 깨워 및 차단 / 깨우기 이러한 작업은 매우 많은 시간이 소요되어 있습니다.

여기에 일부는 아직 최적화가 많이 안하고 후 JDK1.6에 동기화 말할 수있다? 네, 정말, 경량 잠금, 잠금 바이어스 증가, 최적화의 많은 일을하고있다 등 그러나, 경쟁에 많은 스레드가, 비용이 많이 여전히이 증가하는 경우, 당신은 다른 기사에게 소개 믿지 않는다 : 그들이 완전히 동기화 취득 (잠금 헤비급에서 바이어스 잠금)

CAS : 나 같은 사소한 문제

이 대신 동기화 방법 로킹 다른 방법이 없으며, 증가되도록 해당 () 메소드는 스레드 안전입니까?

우리는 나는이 방법으로 다음을 사용하는 경우, 스레드 안전이 증가이다 보장 할 수 있습니까? 다음 단계 :

i 값이 때 0이면 1, 스레드, 메모리 I의 값을 판독하여, 우리의 경우, 즉 K = 0, K 값 그것을했다.

2, 즉 K = J + 1 그래서.

메모리 값 K I에 비해 3, 그들이 동일한 경우, I의 다른 스레드 수정 값이 우리가 메모리에 기록 된 값 (이 경우 1) J 넣어 없음이 수단과 동일하지 않을 경우 ( 나는 평균 값이 다른 스레드에 의해 수정이), 우리는 메모리에 기록 J의 값을 가지고 있지만, 다시이 세 가지 작업을 계속하기 위해 다시 1 단계로 이동하지 않을 것입니다.

코드 워드로 번역이 있습니다 :

public static void increment() {
    do{
        int k = i;
        int j = k + 1;
    }while (compareAndSet(i, k, j))
}

당신이 시뮬레이션에 가면, 당신은 쓰기 스레드 안전을 찾을 수 있습니다.

일부는 메모리를 읽을 수 있지만 상대적으로 쓰기 메모리 및 기타 작업은 ,,, 그 자체로이 단계는 스레드로부터 안전하지 않습니다 아에, 건조뿐만 아니라의 compareAndSet의 세 번째 단계를, 여기에이 작업을 말할 수 있습니다?

당신은 당신이 정말이 과정을 시뮬레이션 할 생각해야하는 것이이 쇼 생각할 수있는,하지만 난 당신이의 compareAndSet 조작, 그는 사실에만 해당하는 운영 체제이다 말하고 싶은 경우 하드웨어 지침을 운영 많은 작업에이 나타납니다 있지만, 내부에 있지만 운영 체제는 그가 원자 실행 것을 보장 할 수 있습니다.

영어 매우 긴 명령어를 들어, 우리는 우리의 compareAndSet 호출 넣어, 그래서 짧은 그를 전화를 사용하려면 CAS에게 그것을.

이 발생하기 때문에,이 메커니즘의 CAS 문구의 사용은 이러한 방법으로, 더 나은 프로그램 실행을 할 수 사물의 장애물이 없었다, 잠그지 경쟁이 있음을 말할 수있다, 스레드 안전합니다.

자바에서는,이 클래스는 예를 들어, CAS 원자를 제공합니다 :

  1. AtomicBoolean
  2. AtomicInteger
  3. AtomicLong
  4. AtomicReference

당신은 어떻게 그것을 사용합니까? 다음과 같이 개정했다 위에 나는 예를 취할 것입니다, 코드는 다음과 같습니다

public class CASTest {
    static AtomicInteger i = new AtomicInteger(0);

    public static void increment() {
        // 自增 1并返回之后的结果
        i.incrementAndGet();
    }
}

CAS : 비밀리에 제 값을 변경

이러한 CAS의기구는 증분 () 메소드를 보장 할 수 있지만, 몇 가지 문제는, 예를 들면 여전히 존재하지만, 때 즉시, 제 3 단계에서, 스레드 B의 I 값에 1을 더한 실행 되려고 하였다 스레드 I 값을 감소 i가 변경되지 않았으므로 1, 다음을 실행하는 세 번째 단계 스레드, 아무도 스레드 생각 이번에는 변형의 값이다. 그리고 그것은 우리가 일반적으로 말하는 것입니다 ABA의 문제 .

기본 유형의 값에 대해, 이것을 원래의 값 다시 디지털 변화는 큰 영향은 아니지만,이 참조 유형 인 경우, 그것은에 큰 영향을 미칠 것입니다.

버전 제어 그것에

ABA는이 문제를 해결하기 위해 우리는 버전 제어를 도입 할 수, 예를 들어, 때마다 스레드가 수정 두 개의 스레드가 같은 참조를 유지하지만, 참조 된 버전의 값이 업데이트됩니다,하지만 그들은 그렇게 서로 다른 버전이, 우리는 ABA 문제를 방지 할 수 있습니다. 자바는이 클래스 AtomicStampedReference, 당신은 버전 제어를 수행 할 수 있습니다.

CAS에의 Java8 최적화.

모든 스레드가 증가 ()이 메소드를 입력 할 수 있도록이 CAS의 결과로 잠그는 방법에 대한 메커니즘은 없다,이 방법에 너무 많은 스레드가, 문제가있을 것입니다 경우 : 실행되는 스레드가있을 때마다 세 번째 단계, 난의 값은 항상 수정 된 경우, 스레드 그래서 다시 시작하는 첫 번째 단계로 돌아가려면 계속한다.

스레드가 너무 조밀 한, 너무 많은 사람들이 내가 값을 변경할 수 있기 때문에, 어디에서 자원 소비 후 대부분의 사람들은 헛된주기에 실패 수정합니다 :이 문제가 발생합니다.

이 문제를 해결하기 Java8 셀 [] 배열을 도입 그 작동 메커니즘이다 : 다섯 개 스레드가있는 경우 나, 증가 연산자를 수행하기 어려운 다음 다섯 개 스레드 때문에, 상충하지 많은 다음, 그들이 그것에서 CAS를 사용하여, 지금까지로 정상을 수행 할 수 있습니다.

다음 i 증가 연산자에있을 100 개 스레드가있는 경우, 그리고,이 때, 충돌이 크게 증가 될 것이다, 시스템은 이동 셀 어레이 요소들의 서로 다른 스레드에 할당되며, 만약 셀 [10] 그것을 10 매있다 상기 요소를 초기화 셀 어레이의 최종 값 (10 개) 요소 (10) 그래서 그 시스템은, 10 기, 증분 동작 않는 셀 어레이의 각 요소에 100 개 스레드를 넣어 0이고 이 시스템의 값은 소자 (10)에 정리되어 최종적 내가되었다에 동작을 자기 - 에너자이징 100 개 스레드 (100)에 해당 두 100를 얻었다.

물론, 내가 Java8 CAS 구체적으로 우리가 소스에 방문하거나 오 해당 기사를 검색 할 의향이 있습니까 최적화의 일반적인 원리를 설명하기 위해 예를 제공하기 위해 여기입니다.

개요

원칙의 CAS 이해는 AQS의 초석이며, 매우 중요하고, AQS, 나는 기사 AQS를 작성합니다 동시성 프레임 워크, 다음 시간의 초석이다.

형제 데이, 내가 잘 쓰여진 느낄 경우, 선호 수

1, 제에 관심을 지불 원래 마이크로 채널 대중 번호 " 프로그램 재생하려면 잘 생긴 쓰기에 초점을 맞추고, 매일 시간을 누름 건조 기술 문서의" 알고리즘 + 기본적인 컴퓨터 지식 (컴퓨터 네트워크 + + 리눅스 데이터베이스 + 운영 체제), 나는 그 관심을 듣고 좋은이 아닌 오 뛰어난 될 것입니다.

2 점 I 찬양 노래로 , 더 많은 사람들이이 글을 볼 수 있습니다 그래서, 그런데, 헤 헤 날 영감을.

게시 79 개 원래 기사 · 원 찬양 20000 + · 전망 1,630,000 +

추천

출처blog.csdn.net/m0_37907797/article/details/104710698