2014-07-16 2 views
1

다음 코드는 프로그램에서 하나의 스레드 만 실행 중이더라도 내 응용 프로그램이 멈추게합니다.쓰기 잠금을 읽기 잠금으로 강등시킬 때의 TMultiReadExclusiveWriteSynchronizer의 동작

semaphoreboost::shared_ptr<TMultiReadExclusiveWriteSynchronizer>입니다. 코멘트 v.ouddou

if (semaphore) 
{ 
    semaphore->BeginWrite(); 

    // Perform write operations on the shared object here. 

    semaphore->BeginRead(); 
    semaphore->EndWrite(); 

    // Perform read-only operations on the object, allowing other threads to also read. 

    semaphore->EndRead(); 
    semaphore->BeginWrite(); // Program locks up here. 
} 

디버그 정보위한 @.

코드를 단계별로 살펴보면 하나의 스레드 만 있습니다. 이것은 윈도우 애플리케이션입니다. 프로그램 엔트리 포인트는 WinMain입니다. 나는 죽음의 선 (마지막 semaphore->BeginWrite()에 단계 때 나는 그것을 중지하는 경우

는, 프로그램이 정지하고, 두 개의 스레드가 내 메인 스레드 어셈블리 땅에 있지만 호출 스택이 WaitForSingleObject입니다 -.>WaitForSingleObjectEx ->ZwWaitForSingleObject

진입 점 RtlUserThreadStart에 스택 정보가없는 두 번째 스레드가 있습니다.이 스레드는 응용 프로그램을 일시 중지 할 수 있도록 만들어졌습니다. 내 코드는 아무 것도 않습니다. 이 시점에서 두 번째 스레드를 만드는 의미.

+0

디버그에서 실행할 수 있으면 디버거의 "일시 중지"를 누르고 프로세스에서 실행중인 모든 스레드의 스택을 검사하여 해당 위치를 확인할 수 있습니다. 주 스레드 만있는 경우 스레드가 예약 취소 된 통화에있는 경우 스택이 의미가 없을 수 있습니다. 신호를 기다리는 세마포어처럼. 이 경우 스레드가 대기열로 이동하고 OS가 즉시 다른 일정을 예약하므로 스택이 일반적으로 그런 경우에는 의미가 없습니다. –

+0

기본적으로 이것은 TMultiReadExclusiveWriteSynchronizer 구현의 버그 인 것 같습니다. 그러나 당신이 먼저'BeginRead'를 호출 한 다음 꽤 쓰기 잠금 ('EndWrite')을하고'EndRead'를 호출하는 유스 케이스는 어쨌든 꽤 이상합니다. 왜 이것을 필요로하는지 설명 할 수 있습니까? – Daniel

+0

@ v.oddou 당신이 말한 것에 대한 응답으로 몇 가지 정보를 추가했습니다. – QuestionC

답변

0

이것은 문제를 해결 한 것 같습니다. 그러나 독서 중 교착 상태를 막기위한 종교적인 섹션.

// Care: Two threads attempting to acquire the locks here would deadlock. 
critical_section->Acquire(); 
semaphore->BeginRead(); 
semaphore->BeginWrite(); 
critical_section->Leave(); 

// Perform write operations on the shared object here. 

semaphore->EndWrite(); 

// Perform read-only operations on the object, allowing other threads to also read. 

semaphore->EndRead(); 

semaphore->BeginWrite(); // No longer deadlocks. 
+0

사실상 중요한 섹션은 필요하지 않습니다. "수정"은'BeginRead'와'BeginWrite'를 재정렬하는 것입니다 (예전 코드는'BeginWrite','BeginRead','EndWrite','EndRead'였습니다. 지원되지 않는 경우입니다) – Daniel