IT

인증서 대 원자

lottoking 2020. 8. 13. 06:50
반응형

인증서 대 원자 [중복]


이 질문에 이미 답변이 있습니다.

나는 줄 아래 어딘가에서 읽었다.

Java 휘발성 키워드는 원 자성을 의미하지 않습니다. 선언을 선언 한 후 ++작업이 원자 적이라는 오해입니다 . 작업을 원자 적으로 만들려면 여전히 synchronizedJava에서 메소드 또는 블록을 사용하여 독점 액세스를 보장해야합니다 .

두 스레드 그렇다면 volatile가 동시에 기본 변수를 공격하면 어떻게 될까요?

그것은 누구든지 그것을 그것을 잠그고 그 값을 먼저 설정한다는 것을 의미합니까? 그리고 그 사이에 다른 내용가 나타나서 첫 번째 숫자가 값을 변경하는 동안 이전 값을 읽지면 새롭고 이전 값을 읽지 않습니다.

Atomic 키워드와 volatile 키워드의 차이점은 무엇입니까?


volatile키워드 의 효과 는 해당 변수에 대한 각 식별 또는 쓰기 작업이 원자 적이라는 것입니다.

그러나 한 번의 읽기와 한 번의 쓰기를 수행하는 i++것과 같은 하나 이상의 읽기 / 쓰기가 필요한 작업은 다른 하나의 읽기와 쓰기 사이에 쓸 수 있기 때문에 원 자성 i = i + 1아닙니다i .

Atomic클래스처럼 AtomicInteger하고 AtomicReference, 특별히 증가 포함 원자 적 동작들의 넓은 다양성을 제공한다 AtomicInteger.


Volatile과 Atomic은 두 가지 다른 개념입니다. 휘발성은 특정 예상 (메모리) 상태가 여러 번에 참임을 보장하는 반면 Atomics는 변수에 대한 작업이 원자를 수행해야합니다.

Java에서 두 개의 목적에 대한 다음 예제를 사용합니다.

예 A :

value = 1;
done = true;

예 B :

if (done)
  System.out.println(value);

시작 value = 0done = false스레딩의 규칙은 값을 출력하지 않습니다. 우리에게 알려줍니다. 또한 그 시점에서 가치 가 정의되지 않았습니다! 이를 위해 필요한 비용에 대해 Java 메모리 관리 (복잡 할 수 있음)에 대해 설명합니다. 간단히 말해서 코드는 변수의 로컬 복사본을 생성 할 수 있으며 JVM 은이를 최적화하기 위해 코드를 재정렬 할 수 있으므로 위의 코드가 보장되지 않습니다. 정확히 그 순서대로 실행됩니다. done을 true 설정 한 다음 값을 1 설정하면 JIT 최적화의 결과가 될 수 있습니다.

volatile세련된 변수의 액세스의 순간에, 새로운 값이 다른 즉시 있음을 볼 수 있는지 보장 코드가 즉시 볼 수있는 기대 보장 코드가 있음, 실행 보장 순서. 따라서 위 코드의 경우 휘발성으로 정의 done하면 스레드 B가 변수를 확인할 때마다 해당 변수가 false 또는 true이고 true이면 1로 설정됩니다.value

휘발성 의 부작용으로 변수의 값은 전체에 원자 적으로 실행 속도의 매우 약간 비용으로 설정됩니다. 그러나 이것은 대부분의 경우에 변수 (64 비트) 변수 (또는 다른 것)를 사용하는 32 비트 시스템에서 가장 중요하며, 대부분의 경우 적 변수를 설정합니다. 그러나 원자 적 액세스와 원자 적 작업 사이에는 중요한 차이가 있습니다. Volatile은 액세스가 원자 적으로 만 보장하는 반면 Atomics는 작업원자로 이루어 지도록합니다 .

다음 예를 사용합니다.

i = i + 1;

i를 어떻게 정의하든 상관없이 위의 행이 실행될 때 값을 읽는 다른 순서는 i 또는 i + 1을 얻을 수 있습니다. 왜냐하면 연산 이 원자 적이 지 않기 때문 입니다. 다른 경우가 i를 다른 값으로 설정하면 최악의 경우 이전 값을 기반으로 i + 1을 계산하는 중간에 있었기 때문에 최악의 경우 경우 A에 의해 이전의 값으로 다시 설정 될 수 있습니다. 다시 이전 값 + 1로 설정합니다. 설명 :

Assume i = 0
Thread A reads i, calculates i+1, which is 1
Thread B sets i to 1000 and returns
Thread A now sets i to the result of the operation, which is i = 1

AtomicInteger와 같은 원자는 이러한 작업이 원자를 적으로 발생하도록합니다. 따라서 위의 문제는 두 가지 모두 완료 될 것입니다.


멀티 스레딩 환경에는 두 가지 중요한 개념이 있습니다.

  1. 원 자성
  2. 시계

Volatile가시성 문제를 근절하지만 원 자성을 다루게됩니다. Volatile컴파일러가 인증서 변수의 쓰기 및 읽기를 포함하는 것을 재정렬하는 것을 방지합니다. 예 : k++여기 k++에 단일 기계 명령이 아니라 세 개의 기계 명령이 있습니다.

  1. 등록 할 값 복사
  2. 그것을 증가
  3. 다시 배치

변수를 선언해도 volatile작업을 원자 적으로 만들지는 만듭니다. 즉, 다른 노래가 다른 경우에 대해 부실하거나 다른 값인 중간 결과를 볼 수 있습니다.

그러나 AtomicInteger, 비교 및 스왑 명령을AtomicReference 기반으로합니다 . CAS에는 작동 할 메모리 위치 , 예상되는 이전 값 및 새 값의 세 가지 피연산자가 있습니다. 의 값 이 예상되는 이전 값과 일치하는 경우에만 새 값 으로 원자 적으로 업데이트 됩니다 . 그렇지 않으면 아무것도하지 않습니다. 두 경우 모두 현재에있는 값을 반환합니다 . 이것은에서 JVM에 의해 사용되는 , 그들은 같은 함수를 호출 . 이 기능이 기본 프로세서에서 지원되지 않는 경우 JVM은 스핀 잠금으로 이를 구현합니다 .VABCASVBVAVAtomicIntegerAtomicReferencecompareAndSet()


표시된대로 시도 volatile중은 가시성 만 처리합니다.

동시 환경에서 다음 스 니펫을 고려하십시오.

boolean isStopped = false;
    :
    :

    while (!isStopped) {
        // do some kind of work
    }

여기서 아이디어는 일부 스레드가 isStopped루프를 중지 할 시간임을 후속 루프에 표시하기 위해 값을 false에서 true로 변경할 수 있다는 것입니다.

직관적으로 문제가 없습니다. 논리적으로 다른 스레드가 isStoppedtrue가되면 루프가 종료되어야합니다. 현실은 다른 스레드가 isStoppedtrue 가 되더라도 루프가 종료되지 않을 가능성이 있다는 것 입니다.

그 이유는 직관적이지 않지만 최신 프로세서에는 다중 코어가 있고 각 코어에는 다른 프로세서에서 액세스 할 수없는 다중 레지스터와 다중 레벨 캐시 메모리가 있다는 점을 고려하십시오 . 즉, 한 프로세서의 로컬 메모리에 캐시 된 값 은 다른 프로세서에서 실행되는 스레드에 표시 되지 않습니다 . 여기에 동시성의 핵심 문제 중 하나 인 가시성이 있습니다.

Java 메모리 모델은 스레드의 변수에 대한 변경 사항이 다른 스레드에 표시 될 수있는시기에 대해 어떠한 보장도하지 않습니다. 업데이트가 작성되는 즉시 표시되도록하려면 동기화해야합니다.

volatile키워드는 동기화의 약한 형태입니다. 상호 배제 나 원자성에 대해서는 아무 일도하지 않지만 한 스레드의 변수에 대한 변경 사항이 변경되는 즉시 다른 스레드에 표시된다는 보장을 제공합니다. 8 바이트가 아닌 변수에 대한 개별 읽기 및 쓰기는 Java에서 원자 적이므로 변수 선언 volatile은 다른 원 자성 또는 상호 배제 요구 사항이없는 상황에서 가시성을 제공하는 쉬운 메커니즘을 제공합니다.


volatile키워드가 사용됩니다 :

  • 원자가 아닌 64 비트 작업을 원자 적으로 만들려면 : longdouble. (다른 모든 기본 액세스는 이미 원 자성으로 보장됩니다!)
  • 변수 업데이트를 다른 스레드에서 볼 수 있도록 보장 + 가시성 효과 : 휘발성 변수에 기록한 후 해당 변수를 작성하기 전에 표시되는 모든 변수는 동일한 휘발성 변수를 읽은 후 (순서 지정 전) 다른 스레드에 표시됩니다.

java.util.concurrent.atomic.*클래스는에 따라입니다 자바 문서 :

단일 변수에 대한 잠금없는 스레드 안전 프로그래밍을 지원하는 작은 클래스 툴킷입니다. 본질적으로이 패키지의 클래스는 휘발성 값, 필드 및 배열 요소의 개념을 다음 형식의 원자 조건부 업데이트 작업을 제공하는 것으로 확장합니다.

boolean compareAndSet(expectedValue, updateValue);

원자 클래스는 compareAndSet(...)원자 CPU 명령어에 매핑 되는 원자 함수를 중심으로 구축됩니다 . 원자 클래스 변수가하는 것처럼 순서 전 발생을 도입합니다 volatile. (한 가지 예외 :) weakCompareAndSet(...).

자바 문서에서 :

스레드가 weakCompareAndSet에 의해 발생한 원자 변수에 대한 업데이트를 볼 때 weakCompareAndSet 이전에 발생한 다른 변수에 대한 업데이트가 반드시 표시되는 것은 아닙니다.

귀하의 질문에 :

이것은 누구든지 그것을 잠그는 사람이 그 값을 먼저 설정한다는 것을 의미합니까? 그리고 그 사이에 다른 스레드가 나타나서 첫 번째 스레드가 값을 변경하는 동안 이전 값을 읽습니다. 그러면 새 스레드가 이전 값을 읽지 않습니까?

아무것도 잠그지 않습니다. 설명하는 것은 스레드가 적절한 동기화없이 공유 데이터에 액세스하는 경우 결국 발생하는 일반적인 경쟁 조건입니다. 이미 언급했듯이이 경우 변수 volatile선언하면 다른 스레드가 변수의 변경 사항을 볼 수만 있습니다 (값은 한 스레드에서만 볼 수있는 일부 캐시의 레지스터에 캐시되지 않음).

AtomicInteger의 차이점은 무엇입니까 volatile int?

AtomicInteger온 동작을 제공 원자 int적절한 동기화 (예. incrementAndGet(), getAndAdd(...)...) volatile int바로의 가시성 확보 할 int다른 스레드로한다.


두 스레드가 동시에 휘발성 기본 변수를 공격하면 어떻게 될까요?

일반적으로 각각 값을 증가시킬 수 있습니다. 그러나 언젠가는 둘 다 동시에 값을 업데이트하고 총 2 씩 증가하는 대신 두 스레드가 1 씩 증가하고 1 만 추가됩니다.

이것은 누구든지 그것을 잠그는 사람이 그 값을 먼저 설정한다는 것을 의미합니까?

자물쇠가 없습니다. 그것이 바로 그 이유 synchronized입니다.

그리고 그 사이에 다른 스레드가 나타나서 첫 번째 스레드가 값을 변경하는 동안 이전 값을 읽습니다. 그러면 새 스레드가 이전 값을 읽지 않습니까?

예,

Atomic 키워드와 volatile 키워드의 차이점은 무엇입니까?

AtomicXxxx는 휘발성을 래핑하므로 기본적으로 동일합니다. 차이점은 증가를 구현하는 데 사용되는 CompareAndSwap과 같은 더 높은 수준의 작업을 제공한다는 것입니다.

AtomicXxxx는 lazySet도 지원합니다. 이것은 휘발성 집합과 비슷하지만 쓰기가 완료되기를 기다리는 파이프 라인을 지연시키지 않습니다. 그것은 당신이 값을 읽는다면 당신은 단지 쓴다는 것을 의미 할 수 있습니다. 당신은 이전 값을 볼 수 있지만 어쨌든 그렇게해서는 안됩니다. 차이점은 휘발성 설정에는 약 5ns가 걸리고 비트 lazySet은 약 0.5ns가 걸린다는 것입니다.

참고 URL : https://stackoverflow.com/questions/19744508/volatile-vs-atomic

반응형