2017-11-27 7 views
3

albahari atricle에서 멀티 스레딩 학습 중입니다. 아래 표본에 _locker 자물쇠가 필요합니까? 이 (가) EventWaitHandle에 의해 보호되어 있기 때문에 나는 그렇지 않다고 생각합니다. 내가 맞습니까?EventWaitHandle을 가지고 있다면 잠금 장치가 필요합니까

class TwoWaySignaling 
{ 
    static EventWaitHandle _ready = new AutoResetEvent (false); 
    static EventWaitHandle _go = new AutoResetEvent (false); 
    static readonly object _locker = new object(); 
    static string _message; 

    static void Main() 
    { 
    new Thread (Work).Start(); 

    _ready.WaitOne();     // First wait until worker is ready 
    lock (_locker) _message = "ooo"; 
    _go.Set();       // Tell worker to go 

    _ready.WaitOne(); 
    lock (_locker) _message = "ahhh"; // Give the worker another message 
    _go.Set(); 
    _ready.WaitOne(); 
    lock (_locker) _message = null; // Signal the worker to exit 
    _go.Set(); 
    } 

    static void Work() 
    { 
    while (true) 
    { 
     _ready.Set();       // Indicate that we're ready 
     _go.WaitOne();       // Wait to be kicked off... 
     lock (_locker) 
     { 
     if (_message == null) return;  // Gracefully exit 
     Console.WriteLine (_message); 
     } 
    } 
    } 
} 
+2

이 예제에서 '잠금'을 제거하면 실행 순서가 변경 될 수 있습니다. – Rotem

+3

잠금이 필요하지 않으므로 두 AutoResetEvent 간의 ping-ponging이 동기화를 제공하여 스레드가 변수에 동시에 액세스 할 수 없도록합니다. WaitOne() 호출은 다른 스레드에서 변수 업데이트를 볼 수 있도록 메모리 장벽을 제공합니다. 우발적 인 장벽의 이러한 종류의 아주 예쁜 아니지만 드물지 않습니다. Barrier 클래스를 사용하는 것이 좋습니다. SignalAndWait() 메서드를 사용하면이 코드를 훨씬 쉽게 이해할 수 있습니다. 그리고 훨씬 더 효율적입니다. 이해할 수있는 코드는 스레딩 버그를 피하고, 효율적인 코드는 모두를 행복하게 만듭니다. –

답변

3

정확합니다.

이러한 종류의 문제는 시행 착오를 통해 간단히 테스트 할 수 없습니다. 그들은 논리적 인 사고로 가장 잘 분석됩니다 :

  • 어떤 코드가 어떤 코드를 실행합니까?
  • 다른 스레드에서 발생할 수있는 내용 ?
  • 다른 스레드가 더 많은 CPU 시간을 얻으면 어떻게됩니까? 등

메인 스레드는 Main()에서 코드를 실행하고 작업자 스레드는 Work()에서 코드를 실행합니다. 그렇게 간단합니다. Work()에서 _message에 대한 액세스 사이에 항상 반면

당신이 중요한 자원이 Main()에서 _message에 대한 액세스를주의 할 것이다 액세스하는 방법을 보면은

_ready.WaitOne(); 

_go.Set(); 

사이에 항상

_go.WaitOne(); 

_ready.Set(); 

따라서, 스레드 중 하나는 항상 _message에 액세스하기 전에 다른 기다리는 잠금이 필요하지 않습니다.

0

스레드가 _message 변수에 동시에 액세스하는 것을 중지했습니다. 여기서 당신의 논리는 항상 충분하지 않고 예측 가능합니다. 때로는 다른 곳에서 읽을 것이고 흐름을 완전히 제어 할 수 없기 때문에 중요한 변수를 잠글 필요가 있습니다.