AutoresetEvent - 두 개의 세트 호출은 스레드 릴리스를 보장하지 않습니다. 왜?

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

문제

MSDN에 대한 AutoRoesetEvent 문서를 읽고 경고 한 다음 경고가 나를 괴롭 히고 있습니다.

"중요 : SET 메서드에 대한 모든 호출이 스레드를 릴리스하는 것은 보장되지 않습니다. 두 번의 통화가 너무 가깝게이면 스레드가 릴리스되기 전에 두 번째 호출이 발생하면 하나의 스레드 만 해제됩니다. 그것은 마치 두 번째 전화가 일어나지 않았는 것처럼 보입니다. 또한, 설정이 대기 중이없고 자동 복 열류가 이미 신호 된 경우에 설정이 호출되면 호출은 효과가 없습니다. "

그러나이 경고는 기본적으로 그런 이유가 그런 이유를 눌러 그런 스레드 동기화 기술을 가지고 있습니다. 예를 들어, 작업을 보유 할 목록이 있습니다. 그리고 목록에 작업을 추가하는 하나의 프로듀서 만 있습니다. 나는 소비자가 있습니다 (둘 이상), 목록에서 일을하기를 기다리고 있습니다 ..이 같은 것들.

생산자 :

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
    }
}
.

위의 경고가 사실이면 두 개의 작업을 매우 빨리 enqueue하면 하나의 스레드 만 작업을 선택할 것입니까? 나는 설정이 원자력이 될 것으로 가정하였고, 그것은 다음을 수행하는 것입니다.

  1. 이벤트 설정
  2. 스레드가 기다리고있는 경우 하나의 스레드를 선택하여 깨어
  3. 이벤트 재설정
  4. 선택한 스레드를 실행합니다.

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

도움이 되었습니까?

해결책

경고가 사실이 아니고 설정된 경우에도 여기에 AutoresetEvent를 사용 하시겠습니까?약간의 생산자가 3 행에 3 가지 이벤트를 대기하고 있으며 소비자가 하나 있습니다.두 번째 작업을 처리 한 후 소비자가 블록을 처리하고 절대로 셋째를 처리하지 않습니다.

readerWriterLockslim 동기화의.기본적으로 여러 생산자가 쓸 수지를 가질 수 있지만 큐 크기 만 읽는 동안 소비자가 오랫동안 생산자를 잠그고 싶지 않아야합니다.

다른 팁

MSDN의 메시지는 실제로 유효한 메시지입니다. 내부적으로 무슨 일이 일어나고 있는지 다음과 같습니다.

  1. 이벤트에 대한 대기
  2. 스레드 B 이벤트를 설정합니다
  3. [스레드 A가 스핀 락에있는 경우]
    1. [예] 스레드 A 이벤트가 설정되었음을 감지하고, 부적합하고 작업을 다시 시작합니다.
    2. [no] 이벤트는 스레드 A를 깨우려면 깨우므로 깨우기 위해 스레드 A가 이벤트를 다시 시작하지 않을 것입니다.

      스레드 B는 스레드 A가 비즈니스를 계속하기 위해 기다리지 않으므로 내부 논리가 동기하지 않습니다. thread a가 일단 작업을 계속하고 스레드 B가 기다려야하는 스레드 A가 신호를 보내는 임시 ManualReseTevent를 도입 하여이 동기식을 만들 수 있습니다. 이것은 Windows 스레딩 모델의 내부 작업으로 인해 기본적으로 수행되지 않습니다. 나는 문서가 오도 된 것임을 추측하지만 설정된 방법이 하나 이상의 대기 중간만을 릴리스한다는 것을 의미합니다.

      optionswetch.collections.concurrent의 System.Collections.Concurrent의 클래스를 볼 것을 제안 할 것이라고 제안합니다 .NET 4.0에서 도입 된 BCL의 클래스 네임 스페이스

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