2014-02-21 6 views
0

하나의 스레드에서 변수를 작성한 경우 ManualResetEventWaitOne() 메소드를 사용하여 다른 스레드가 같은 변수에 값을 할당하고 EventWaitHandel을 신호 할 때까지 블록합니다. 첫 번째 스레드에서 변수를 읽으려고하면 다른 스레드가 할당 한 값을 항상 확보 할 수 있습니까?EventWaitHandel을 사용하는 경우 다른 스레드에서 읽을 때 하나의 스레드에서 할당 된 변수가 "스레드 안전"합니까?

(내가 아는 한 모든 메모리 장벽을 사용하지 않았기 때문에 약간의 최적화로 인해 CPU 캐시에서 값을 얻을 수 없다는 두려움이 있습니다.)

예컨대

var str = "multi-threading is hard!"; 
var mre = new ManualResetEvent(false); 
Task.Factory.StartNew(() => 
    { 
     str = Console.ReadLine(); 
     mre.Set(); 
    )); 
mre.WaitOne(); 
Console.WriteLine(str); 
+0

'WaitOne

브라이언 기드온과 한스 옆모습 함께 암시 적 메모리 장벽을 소개 .NET Framework의 여러 클래스의 좋은 목록을 넣어()'. 어디에? 나는 Console.WriteLine 전에 그것을 기대할 것이다. – Georg

+0

그래, 그 덕분에 – markmnl

답변

1

이러한 지침은 생산 스레드에서, 필드 할당이 항상 소비 스레드에서, 필드가 항상 후 을 읽을 수 있습니다, 손잡이가 신호됩니다 전에 발생, 것, 즉, 순서가되지 않습니다 핸들이 신호됩니다. 지침이 이쌍 어떠한 다시 주문 수 있다면 (두 번째 스레드가 핸들이 신호를했다 전에 필드 을 읽을 수 있다면, 예를 들어,)

는, 당신은 올바른 값이 표시되지 것이다.

WaitOne()에는 필요한 암시 적 의미를 부여하는 암시적인 메모리 장벽이 있습니다. Memory barrier generators

상세 정보 : 당신은 당신이 사용이라고 말했다 Acquire and release semantics/Acquire and release fences

+0

여기에서 순서 바꾸기의 관련성을 보지 못했지만 메모리 장벽이 함축되어 암시 적으로 정리됩니다. – markmnl

+0

아, 감사합니다. 덧붙여 말하자면, 명령을 재정렬 할 수 없다는 것을 어떻게 알 수 있습니까? 그것은 메모리 장벽 때문입니까? – markmnl

+0

@markmnl 다시 정렬해야하는 이유를 설명하는 첫 번째 단락을 편집했습니다. – dcastro

0

내 변수는 람다 식을 사용하고 있기 때문에, 컴파일러는 컴파일러가 생성 한 클래스의 필드에이 로컬 변수 변 포착 변수, 즉이다. Afaik,이 컴파일러 생성 필드는 volatile으로 표시되지 않으므로 캐싱 될 수 있습니다.

편집 : 실제로 필드는 휘발성이 아닙니다.

컴파일러가 직접 클래스를 작성하지 않아도 캐싱을 방지 할 수 있습니다. 그러나 이것은 물론 코드의 간결함을 방해합니다.

+0

넵 나는 그것을 캡처 알고 있지만, 내 자신의 클래스와 함께 문제를 다시 쓴 경우 문제가 여전히있을 것 - 나는 그것도 '휘발성'을 표시 할 수 있습니다. 어쨌든 기억 장벽이 암묵적이므로 아무런 필요도없는 것 같습니다. – markmnl