2012-02-29 1 views
2
내가 MSDN에 AutoResetEvent 설명서를 읽고 경고가 좀 날 귀찮게 다음되었다

..AutoResetEvent - 두 건의 호출이 빠르게 스레드 릴리즈를 보장하지 않습니다 - 왜?

는 "중요 : 는 설정 방법에 대한 모든 호출이 스레드를 발표 할 예정이다 보장이 없습니다 두 통화가 서로 너무 가까이 있다면, 그래서. 두 번째 호출은 스레드가 해제되기 전에 발생하고 하나의 스레드 만 해제되며 두 번째 호출은 발생하지 않은 것처럼 동작하며 대기중인 스레드가없고 AutoResetEvent가 이미 신호를 받으면 Set이 호출되면 호출 효과가 없다. "

그러나이 경고는 기본적으로 그러한 스레드 동기화 기술을 갖는 이유를 없애줍니다. 예를 들면 나는 일자리를 잡을 목록을 가지고있다. 그리고 목록에 일자리를 추가 할 생산자는 단 한 명뿐입니다. 나는 .. 이런 식으로 뭔가를 목록에서 작업을 얻기 위해 기다리고, 소비자 (이상 1보다)이 ..

프로듀서 :

void AddJob(Job j) 
{ 
    lock(qLock) 
    { 
     jobQ.Enqueue(j); 
    } 

    newJobEvent.Set(); // newJobEvent is AutoResetEvent 
} 

소비자

void Run() 
{ 
    while(canRun) 
    { 
     newJobEvent.WaitOne(); 

     IJob job = null; 

     lock(qLock) 
     { 
      job = jobQ.Dequeue(); 
     } 

     // process job 
    } 
} 

하는 경우 위의 경고는 사실입니다. 그런 다음 두 개의 작업을 매우 빠르게 대기열에 넣으면 단 하나의 스레드 만 작업을 선택합니다. 그렇지 않습니까? 내가 설정은 원자 될 것이라는 가정하에 있었다, 즉, 다음을 수행입니다 :

  1. 가 이벤트를 다시 스레드가 대기하는 경우,
  2. 을 깨워 하나 개의 스레드를 선택
  3. 이벤트를 설정
  4. 선택한 스레드를 실행하십시오.

그래서 기본적으로 MSDN의 경고에 대해 혼란스러워합니다. 그것은 유효한 경고입니까?

+0

예,이 코드만이 일을하려고 정확히 않는 .NET 4.0에 도입 우연히. 많은 바퀴벌레, 구글 'C# 생산자 소비자 대기열'을 많이 만들지 마십시오. –

+0

생산자 소비자 중 대부분이 검색을 찾았으며 대기/신호 접근 방식을 사용합니다. 그 접근 방식의 문제점은 제가 노동자를 그만두기를 원할 때 나는 가짜 일자리를 제출해야한다는 것입니다. 그러나 이벤트를 사용할 수 있다면 작업자가 두 가지 이벤트를 기다리게 할 수 있습니다. 하나는 작업을하고 다른 하나는 종료합니다. 기분이 더 깨끗해 .. – cgcoder

답변

2

경고가 true가 아니고 Set이 원 자성 인 경우에도 여기에서 AutoResetEvent를 사용하는 이유는 무엇입니까? 일부 생산자가 연속으로 3 개의 이벤트를 대기열에두고 하나의 소비자를 보유하고 있다고 가정 해 봅시다. 두 번째 작업을 처리 한 후 소비자는 세 번째 작업을 차단하고 절대로 처리하지 않습니다.

이 유형의 동기화에는 ReaderWriterLockSlim을 사용합니다. 기본적으로 쓰기 잠금을 가질 수 있도록 여러 제작자가 필요하지만 대기열 크기 만 읽는 동안 소비자가 생산자를 오랫동안 잠그지 않도록하고 싶지는 않습니다.

2

MSDN의 메시지는 실제로 유효한 메시지입니다. 무엇 내부에서 일어나고있는 것은이 같은 것입니다 : [스레드 A가 스핀 록에있는 경우] 스레드 B가 이벤트를 설정

  • 이벤트에 대한

    1. 스레드 A의 대기
      1. [예] 스레드 A가 있음을 감지 이벤트가 설정되고 해제되고 작업을 재개합니다.
      2. [no] 이벤트는 스레드 A에게 깨우기 위해 알려주고, 일단 깨우면 스레드 A는 이벤트 작업을 다시 시작합니다.스레드 B가 사업을 계속 스레드 A 기다리지 않기 때문에 내부 논리 동기되지 않는다는

    참고. 스레드 A가 작업을 계속하고 스레드 B가 기다려야 할 때 신호를 보내야하는 임시 ManualResetEvent를 도입하여이를 동기화 할 수 있습니다. 이것은 Windows 스레딩 모델의 내부 작업으로 인해 기본적으로 수행되지 않습니다. 나는 설명서가 오해의 소지가 있지만 Set 메소드가 하나 이상의 대기중인 스레드만을 해제한다고 말한 것이 맞을 것이다. 또한

    내가 BCL의 System.Collections.Concurrent 네임 스페이스의 BlockingCollection 클래스를보고 당신을 제안 당신이

  • 관련 문제