LeaveCriticalSection 한번만 호출하기

CRITICAL_SECTION 는 한 프로세스내에서의 동기화를 위한 object이다.

http://msdn2.microsoft.com/en-us/library/ms682530.aspx

이미 CRITICAL_SECTION 을 소유한 스레드가 다시 EnterCriticalSection 으로 그것을 소유하려고 하는경우 에러없이 넘어간다.
그러나 한번 LeaveCriticalSection 으로 CRITICAL_SECTION 을 해제한 다음 다시LeaveCriticalSection 을 호출하면, 즉 소유하지 않는 스레드에서 LeaveCriticalSection 을 호출하면 다음번 EnterCriticalSection 호출시에 deadlock 이 발생한다.

이것을 막자면 현재 스레드가 그 Critical section 을 소유하고 있는 경우에만 LeaveCriticalSectin 을 호출하도록 하여야 한다.

아래와 같이 동기화 클래스를 만들면 이 문제를 해결할수 있다.

*** 더 좋은 방법을 알려주시면 감사하겠습니다...

class CSingleCriticalSection
{
public:
    CSingleCriticalSection();
    ~CSingleCriticalSection();
    BOOL IsCurrentThreadLocked();
    void Lock();
    void Unlock();
protected:
    CCriticalSection m_section;
    DWORD    volatile m_dwThreadId;
};

inline CSingleCriticalSection::CSingleCriticalSection()
{
    InterlockedExchange((PLONG)&m_dwThreadId, 0);
}

inline CSingleCriticalSection::~CSingleCriticalSection()
{
    Unlock();
}

BOOL inline CSingleCriticalSection::IsCurrentThreadLocked()
{
    return m_dwThreadId && m_dwThreadId == GetCurrentThreadId();
}

void inline CSingleCriticalSection::Lock()
{
    if(!IsCurrentThreadLocked())
    {
        m_section.Lock();
        InterlockedExchange((PLONG)&m_dwThreadId, (LONG)GetCurrentThreadId());
    }
}

void inline CSingleCriticalSection::Unlock()
{
    if(IsCurrentThreadLocked())
    {
        m_section.Unlock();
        InterlockedExchange((PLONG)&m_dwThreadId, (LONG)0);
    }
}

이 글과 관련있는 글을 자동검색한 결과입니다 [?]

by 아폴로 | 2008/04/19 20:12 | 컴퓨터 | 트랙백 | 덧글(1)

트랙백 주소 : http://corapollo.egloos.com/tb/257331
☞ 내 이글루에 이 글과 관련된 글 쓰기 (트랙백 보내기) [도움말]
Commented by 아폴로 at 2008/04/22 00:02
Unlock 에서 Deadlock 이 걸릴수 있다.
아래와 같이 수정한다.

void inline CSingleCriticalSection::Unlock()
{
if(IsCurrentThreadLocked())
{
InterlockedExchange((PLONG)&m_dwThreadId, (LONG)0);
m_section.Unlock();
}
}

:         :

:

비공개 덧글

◀ 이전 페이지          다음 페이지 ▶