programing

휘발성 대 원자성

prostudy 2022. 5. 11. 22:00
반응형

휘발성 대 원자성

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

' 키워드'는 ''를 게 휘발성을 한 뒤 '자바'는 '자바'를 '자바'로 표기한다'는 게 다. 그것은 휘발성을 선언하고 나서++이 될 운영은자이를 가 있다. 운영 원자를 만들기 위해 당신은 여전히 다음을 사용하여 독점적인 접근을 보장해야 한다.synchronizedJava에서 메서드 또는 블록.

그래서 만약 두 개의 실이 a를 공격한다면 어떻게 될까?volatile원시적인 변수를 동시에 사용할 수 있는가?

이것은 누가 먼저 그것의 가치를 정할 것인가를 의미한다.그리고 그 사이에 어떤 다른 실이 올라와서 첫 번째 실이 그 가치를 바꾸고 있을 때 옛 가치를 읽게 된다면, 그러면 새로운 실이 그 옛날 가치를 읽지 않을까?

Atomic 키워드와 휘발성 키워드의 차이점은?

volatile키워드는 해당 변수에 대한 각 개별 읽기 또는 쓰기 작업이 원자적으로 모든 스레드에 표시되도록 하는 것이다.

그러나 특히 다음과 같이 둘 이상의 읽기/쓰기가 필요한 작업i++ , 에 하는 것.i = i + 1, 한 읽기와 한 쓰기는 -- 다른 스레드가 쓸 수 있기 때문에 원자적이지 않다.i읽기와 쓰기의 중간에

Atomic같은 계급AtomicInteger그리고AtomicReference, 원자적으로 보다 다양한 작업을 제공하며, 특히 다음을 위한 증분을 포함한다.AtomicInteger.

휘발성과 원자성은 서로 다른 개념이다.휘발성은 특정 기대(메모리) 상태가 서로 다른 스레드에 걸쳐 참임을 보장하며, 아톰틱스는 변수에 대한 작동이 원자적으로 수행되도록 보장한다.

Java에서 다음 두 스레드의 예를 들어 보십시오.

스레드 A:

value = 1;
done = true;

스레드 B:

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

value = 0그리고done = false스레드 B가 값을 인쇄할 것인지 여부가 정의되지 않았다는 것을 스레드 규칙이 알려준다.더욱이 그 시점에서도 가치는 정의되지 않는다!이를 설명하려면 Java 메모리 관리(복잡할 수 있음)에 대해 간략하게 설명하십시오.스레드는 변수의 로컬 복사본을 만들 수 있으며, JVM은 이를 최적화하기 위해 코드를 재주문할 수 있으므로 위의 코드가 정확히 그 순서로 실행된다는 보장은 없다.true로 설정한 다음 을 1로 설정하는 것은 JIT 최적화의 가능한 결과일 수 있다.

volatile오직, 그러한 변수에 접근하는 순간, 새로운 값이 다른 모든 스레드에 즉시 보여지고 실행 순서가 코드의 예상된 상태에 있도록 보장한다.그래서 위 코드의 경우, 정의하기done휘발성은 스레드 B가 변수를 점검할 때마다 거짓 또는 참이며, 그것이 사실이라면 다음 중 하나를 보장할 것이다.value역시 1로 설정되었다.

휘발성의 부작용으로서, 그러한 변수의 값은 (실행 속도의 매우 작은 비용으로) 원자로 설정된다.그러나 이는 긴(64비트) 변수(또는 유사한 변수)를 사용하는 32비트 시스템에서만 중요하며, 다른 대부분의 경우 변수를 설정/읽는 것은 원자적이다.그러나 원자핵 접근과 원자력 운영 사이에는 중요한 차이가 있다.휘발성은 접근이 원자적으로만 보장하고, 아토믹스는 조작이 원자적으로 이루어지도록 보장한다.

다음 예를 들어 보십시오.

i = i + 1;

i를 어떻게 정의하든, 위의 선이 실행될 때에만 값을 읽는 다른 스레드가 원자가 아닌 연산을 하기 때문에 i, 또는 i + 1을 얻을 수 있다.다른 나사산이 i를 다른 값으로 설정하면 최악의 경우, 이전 값을 기준으로 i+1을 계산하는 중이었기 때문에 스레드 A에 의해 이전의 무엇으로 다시 설정될 수 있으며, 그 다음 다시 i를 이전 값 + 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와 같은 원자력은 그러한 작전이 원자적으로 일어나도록 보장한다.따라서 위의 문제는 발생할 수 없으며, 두 개의 스레드가 모두 완료되면 나는 1000 또는 1001이 될 것이다.

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

  1. 원자성
  2. 가시성

volatile키워드는 가시성 문제를 근절하지만 원자성을 다루지 않는다.volatile예를 들어, 컴파일러가 휘발성 변수의 쓰기 및 후속 읽기와 관련된 지침을 다시 정렬하지 못하도록 할 것이다.k++, 자,k++단일 기계 지침이 아니라 세 가지:

  1. 값을 레지스터에 복사한다.
  2. 값을 증가시킨다.
  3. 그것을 도로 갖다 놓다

그래서 변수를 다음과 같이 선언한다 하더라도.volatile, 이것은 이 조작을 원자성으로 만들지 않을 것이다; 이것은 다른 스레드가 다른 스레드에 대해 오래된 또는 원하지 않는 값인 중간 결과를 볼 수 있다는 것을 의미한다.

반면, 는 비교스왑 지침을 기반으로 한다.CAS에는 세 개의 피연산자가 있다: 메모리 위치V할 것인가,되는 옛 인 『동화』, 『이』A, 그리고 새로운 가치B.CAS원자적으로 갱신하다.V새로운 가치로B, 그러나 값이 다음 값인 경우에만V기대했던 옛 가치와 일치하다.A; 그렇지 않으면 아무것도 하지 않는다. 두 모 두 value value value value 에 있는 값을 반환한다V . The . The.compareAndSet()의 방법.AtomicInteger그리고AtomicReference기본 프로세서가 지원하는 경우 이 기능을 활용하고, 그렇지 않은 경우 JVM은 스핀 잠금을 통해 이 기능을 구현한다.

표시된 대로 시도하면,volatile가시성만을 다룬다.

동시 환경에서 다음 조각을 고려하십시오.

boolean isStopped = false;
    :
    :

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

여기서의 생각은 어떤 실이 그 가치를 바꿀 수 있다는 것이다.isStopped루프를 중단해야 할 때라는 것을 다음 루프로 나타내기 위해 거짓에서 참으로.

직관적으로 문제가 없다.다른 스레드가 만드는 경우 논리적으로isStopped참과 같을 경우 루프가 종료되어야 한다.현실은 다른 실이 만들어지더라도 루프는 결코 끝나지 않을 것 같다.isStopped진실에 필적하는

그 이유는 직관적이지는 않지만, 현대의 프로세서는 여러 개의 코어를 가지고 있고 각 코어는 다른 프로세서가 접근할 수 없는 여러 개의 레지스터와 여러 수준의 캐시 메모리를 가지고 있다는 점을 고려한다.즉, 한 프로세서의 로컬 메모리에 캐시된 값은 다른 프로세서에서 실행되는 스레드에 보이지 않는다.여기에는 동시성의 중심 문제 중 하나인 가시성이 있다.

Java Memory Model은 한 스레드의 변수에 대한 변경이 다른 스레드에 언제 가시화될 수 있는지에 대해 어떠한 보증도 하지 않는다.업데이트가 이루어지는 즉시 눈에 잘 띄도록 보장하려면 동기화해야 한다.

volatile키워드는 약한 형태의 동기화 입니다.상호 배제나 원자성에는 아무런 도움이 되지 않지만, 그것은 한 가닥의 변수에 대한 변경이 만들어지는 즉시 다른 나사산에 가시화될 것이라는 보증을 제공한다.8바이트가 아닌 변수에 대한 개별 읽기 및 쓰기는 Java에서 원자적이기 때문에 변수를 선언한다.volatile다른 원자성 또는 상호 배제 요건이 없는 상황에서 가시성을 제공하기 위한 쉬운 메커니즘을 제공한다.

volatile키워드 사용:

  • 비원자성 64비트 연산을 원자성 작업으로 설정하려면:long그리고double은 이미 (다른 모든 원시적 접근은 이미 원자적인 것으로 보장되어 있다!)
  • 다른 스레드 + 가시성 효과로 볼 수 있도록 보장하는 변수 업데이트 만들기: 휘발성 변수에 쓰기 전에 표시되는 모든 변수, 동일한 휘발성 변수(주문 전 사전 준비)를 읽은 후 다른 스레드에 해당 변수를 쓰기 전에 표시되는 모든 변수를 볼 수 있게 한다.

java.util.concurrent.atomic.*클래스는 Java 문서에 따라 다음과 같다.

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

boolean compareAndSet(expectedValue, updateValue);

원자 계급은 원자 주위에 형성된다.compareAndSet(...)원자 CPU 명령에 매핑되는 기능.원자 계급은 명령 전 발생을 다음과 같이 소개한다.volatile변수가 그렇다.(한 가지 예외:weakCompareAndSet(...)).

Java 문서:

스레드가 약한 CompareAndSet로 인해 발생한 원자 변수에 대한 업데이트를 볼 때 스레드가 약한 CompareAndSet 이전에 발생한 다른 변수에 대한 업데이트를 반드시 볼 필요는 없다.

질문할 내용:

이것은 누가 먼저 그것의 가치를 정할 것인가를 의미한다.그리고 그 사이에 첫 번째 실이 그 가치를 바꾸고 있을 때 어떤 다른 실이 올라와서 옛 가치를 읽게 된다면, 그러면 새로운 실이 그 옛날 가치를 읽지 않을까?

아무것도 잠그지 않는 경우, 스레드가 적절한 동기화 없이 공유 데이터에 액세스할 경우 결국 발생하는 일반적인 레이스 조건.한 바와 변수 은 한국에서도 할 수 있다.volatile이 경우 다른 스레드가 변수의 변화를 볼 수 있도록만 보장한다(한 스레드로만 표시되는 일부 캐쉬의 레지스터에는 값이 캐시되지 않는다).

와의 차이점은 무엇인가?AtomicInteger그리고volatile int?

AtomicInteger에 대한 원자력 운영 제공int적절한 동기화(예: incrementAndGet()getAndAdd(...), ...),volatile int이 모든 것을 볼 수 있게 해 줄 겁니다int다른 실에

그렇다면 두 개의 실이 동시에 휘발성 원시 변수를 공격한다면 어떻게 될까?

보통 각자가 그 가치를 증가시킬 수 있다.그러나 때때로 두 스레드는 동시에 값을 업데이트하고 총 2만큼 증가시키는 대신 두 스레드가 모두 1씩 증가하며 1만 추가된다.

이것은 누가 먼저 그것의 가치를 정할 것인가를 의미한다.

자물쇠가 없다.그것이 바로 그것이다.synchronized에 대한 것이다.

그리고 그 사이에 첫 번째 실이 그 가치를 바꾸고 있을 때 어떤 다른 실이 올라와서 옛 가치를 읽게 된다면, 그러면 새로운 실이 그 옛날 가치를 읽지 않을까?

Atomic 키워드와 휘발성 키워드의 차이점은?

AtomicXxxxx는 휘발성을 포장하여 기본적으로 동일하며, 증분을 구현하는 데 사용되는 CompareAndSwap과 같은 높은 수준의 연산을 제공한다는 점이 다르다.

AtomicXxxx는 또한 게으른 세트를 지원한다.이것은 휘발성 세트와 같지만, 쓰기가 완료되기를 기다리는 파이프라인을 멈추지는 않는다.그것은 여러분이 단지 쓰는 가치를 읽는다면 오래된 가치를 볼 수도 있지만, 어쨌든 그렇게 해서는 안 된다는 것을 의미할 수 있다.차이점은 휘발성 설정에는 약 5ns가 소요되며, 약간 게으르다는 것이다.세트는 약 0.5 ns가 소요된다.

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

반응형