인터 로크 클래스를 사용하는 것과 대조적으로 휘발성 키워드를 사용한다는 장점이 있습니까?

StackOverflow https://stackoverflow.com/questions/1701216

문제

다시 말해, 일반 변수와 인터 로크 클래스로 해결할 수없는 휘발성 변수로 무언가를 할 수 있습니까?

도움이 되었습니까?

해결책

편집 : 질문이 크게 다시 작성되었습니다

이 질문에 대답하기 위해, 나는 그 문제에서 조금 더 뛰어 났고 몇 가지 사항을 발견했습니다. volatile 그리고 Interlocked 내가 몰랐다. 나뿐만 아니라이 토론과 다른 사람들에게 이것에 대해 읽는 것을 분명히하겠습니다.

  • volatile 읽기/쓰기는 재주문에 면역이되어야합니다. 이것 읽기와 쓰기를 의미합니다 ~ 아니다 다른 행동을 의미합니다.
  • 휘발성 CPU, 즉 하드웨어 수준에서 강요되지 않습니다 (x86 어느 읽기/쓰기). 컴파일러 또는 CLR 최적화를 방지합니다.
  • Interlocked Atomic Assembly 지침을 사용하여 CompareexChange (cmpxchg), 증분 (inc) 등;
  • Interlocked 사용합니다 때때로 자물쇠 : a 다중 프로세서 시스템의 하드웨어 잠금; Uni-Processor 시스템에는 하드웨어 잠금이 없습니다.
  • Interlocked 다릅니다 volatile 그것은 a를 사용한다는 점에서 전체 울타리, 휘발성이 반 울타리를 사용하는 곳.
  • 쓰기 후 읽기를 재정렬 할 수 있습니다 당신이 사용할 때 volatile. 그것은 일어날 수 없습니다 Interlocked. VolatileRead 그리고 VolatileWrite `휘발성 (Brian Gideon 덕분에 링크)과 동일한 재주문 문제가 있습니다.

이제 규칙이 있으므로 귀하의 질문에 대한 답변을 정의 할 수 있습니다.

  • 기술적으로 : 그렇습니다. volatile 당신이 할 수없는 것 Interlocked:
    1. 구문 : 글을 쓸 수 없습니다 a = b 어디 a 또는 b 휘발성이지만 이것은 분명합니다.
    2. 재정렬로 인해 휘발성 변수로 작성한 후 다른 값을 읽을 수 있습니다. 당신은 이것을 할 수 없습니다 Interlocked. 다시 말해 : 당신은 될 수 있습니다 더 적은 안전합니다 volatile 그러면 당신은 함께있을 수 있습니다 Interlocked.
    3. 성능: volatile 그렇다면 더 빠릅니다 Interlocked.
  • 의미 적으로 : 아니요 Interlocked 단순히 수퍼 세트를 제공하며 전체 펜싱을 적용하기 때문에 사용하기에 더 안전합니다. 당신은 아무것도 할 수 없습니다 volatile 당신이 할 수없는 것 Interlocked 그리고 당신은 할 수 있습니다 많이 ~와 함께 Interlocked 휘발성으로 할 수 없다는 것 :

    static volatile int x = 0;
    x++;                        // non-atomic
    static int y = 0;
    Interlocked.Increment(y);   // atomic
    
  • 범위 : 예, 변수를 선언합니다 volatile 모든 단일 액세스마다 휘발성이 있습니다. 이 행동을 다른 방식으로 강요하는 것은 불가능하므로 volatile 교체 할 수 없습니다 Interlocked. 다른 라이브러리, 인터페이스 또는 하드웨어가 변수에 액세스하고 언제든지 업데이트하거나 최신 버전이 필요한 시나리오에서 필요합니다.

당신이 나에게 묻는다면,이 마지막 비트는 실제의 실제 요구입니다. volatile 두 프로세스가 메모리를 공유하고 잠금없이 읽거나 쓸 필요가있는 경우 이상적입니다. 변수를 다음과 같이 선언합니다 volatile 이 맥락에서 훨씬 더 안전합니다. 그런 다음 모든 프로그래머가 사용하도록 강요합니다. Interlocked (컴파일러로 강제 할 수 없습니다).


편집 : 다음 인용문은 나의 원래 대답의 일부 였고, 나는 그것을 남겨 두겠습니다 ;-)

The The의 인용 C# 프로그래밍 언어 기준:

비 휘발성 필드의 경우, 재주문 지침을 고려하는 최적화 기술은 예상치 못한 예측할 수없는 결과로 이어질 수 있으며, 동기화없이 필드에 액세스하는 다중 스레드 프로그램에서 자물쇠 진술. 이러한 최적화는 컴파일러, 런타임 시스템 또는 하드웨어에 의해 수행됩니다. 휘발성 필드의 경우 이러한 재주문 최적화가 제한됩니다.

  • 휘발성 필드를 읽는 것을 a라고합니다 휘발성 읽기. 휘발성 읽기는 다음과 같습니다.

  • 휘발성 필드의 글을 a라고합니다 휘발성 쓰기. 휘발성 쓰기에는 "릴리스 시맨틱"이 있습니다. 즉, 명령 시퀀스에서 쓰기 명령 전에 메모리 참조 후에 발생한 후에 보장됩니다.

업데이트: 질문은 크게 다시 작성하고 원래의 응답을 수정하고 "실제"답변을 추가했습니다.

다른 팁

이것은 상당히 복잡한 주제입니다. 나는 조셉 알바 하리를 찾았다 쓰기 .NET 프레임 워크의 다중 스레딩 개념에 대한보다 결정적이고 정확한 소스 중 하나가 되려면 질문에 답변 할 수 있습니다.

그러나 빠르게 요약하기 위해 volatile 키워드와 Interlocked 사용 방법에 따라 클래스. 물론 정상적인 변수로 할 수있는 일을 넘어서고 있습니다.

예 - 값을 직접 볼 수 있습니다.

인터 로크 클래스 만 사용하여 변수에 액세스하는 한 차이가 없습니다. 뭐 휘발성 물질 이는 변수가 특수하다는 것을 컴파일러에게 알려주는 것입니다. 최적화 할 때 값이 변경되지 않았다고 가정해서는 안됩니다.

이 루프를 취합니다.

bool done = false;

...

while(!done)
{
... do stuff which the compiler can prove doesn't touch done...
}

설정하면 done 에게 true 다른 스레드에서는 루프가 종료 될 것으로 예상됩니다. 그러나 완료된 경우 표시되지 않습니다 volatile 그런 다음 컴파일러는 루프 코드가 절대 변경 될 수 없음을 인식 할 수있는 옵션이 있습니다. done 출구 비교를 최적화 할 수 있습니다.

이것은 멀티 스레드 프로그래밍의 어려운 것 중 하나입니다. 문제인 많은 상황은 특정 상황에서만 발생합니다.

나는이 주제에 대한 권위자가되지 않지만 당신은 당신이 살펴 보는 것을 강력히 추천합니다. 이 기사 vaunted Jon Skeet에 의해.

또한 마지막 부분을 살펴보십시오 이 답변 무엇을 자세히 설명합니다 volatile 사용해야합니다.

예, 잠금 대신 휘발성 변수를 사용하여 일부 성능을 얻을 수 있습니다.

잠금은 전체 메모리 장벽으로, 휘발성 변수의 동일한 특성뿐만 아니라 다른 많은 사람들뿐만 아니라 다른 많은 변수입니다. 이미 언급 된 바와 같이 휘발성은 CPU가 캐시 라인의 값을 변경하면 다중 스레드 시나리오에서 다른 CPU가 즉시 값을 보지만 잠금 시맨틱을 전혀 보장하지 않도록합니다.

잠금은 휘발성보다 훨씬 강력하며 불필요한 잠금을 피할 수있는 경우 휘발성을 사용해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top