2015-07-03 65 views
0

我正在爲一個允許線程彼此共享內存的內存緩衝區編寫代碼。我正在嘗試使用關鍵部分和條件變量進行同步。Windows條件變量沒有在預期的時候發信號

這是我的源代碼:

size_t ReadBuffer(char *dst_buffer) 
{ 
    size_t size = 0; 
    EnterCriticalSection(&m_CriticalSection); 

    if (!m_bBufferReady) 
    { 
     printf("ReadBuffer: wait for ready buffer\n"); 
     SleepConditionVariableCS (&BufferNotEmpty, &m_CriticalSection, INFINITE); 
     printf("ReadBuffer: after wait for ready buffer\n"); 
    } 
    if (m_uRealSize == 0) 
    { 

    } 
    memcpy(dst_buffer, m_pBuffer, m_uRealSize); 
    size = m_uRealSize; 
    m_uRealSize = 0; 
    m_bBufferReady = FALSE; 
    LeaveCriticalSection(&m_CriticalSection); 
    WakeConditionVariable (&BufferNotFull); 
    if (size != 0) 
    { 
     SleepConditionVariableCS (&BufferNotEmpty, &m_CriticalSection, INFINITE); 
    } 

    return size; 
} 

size_t WriteBuffer(const char *src_buffer, size_t size) 
{ 
    EnterCriticalSection(&m_CriticalSection); 
    if (m_bBufferReady) 
    { 
     SleepConditionVariableCS (&BufferNotFull, &m_CriticalSection, INFINITE); 
     printf("WriteBuffer: after wait for free buffer\n"); 
    } 
    if (size > m_uBufferSize) 
     size = m_uBufferSize; 
    memcpy(m_pBuffer, src_buffer, size); 
    m_uRealSize = size; 
    m_bBufferReady = TRUE; 
    LeaveCriticalSection(&m_CriticalSection); 
    WakeConditionVariable (&BufferNotEmpty); 
    SleepConditionVariableCS (&BufferNotFull, &m_CriticalSection, INFINITE); 
    return size; 
} 

當WriteBuffer是帶一個零大小的緩衝區它被視爲通信的結束。此時,閱讀線程正確退出,但寫入線程掛起最後一次調用SleepConditionVariableCS

當我使用Windows事件而不是條件變量時,一切正常,所以我不認爲這是算法的問題。但我希望能夠使用條件變量而不是事件。有沒有限制使用條件變量?或者也許它以某種方式連接到關鍵部分?

怎麼回事,我該如何解決?

+0

「最後呢......」到底是什麼?沒有代碼退出線程。 –

+0

爲什麼'ReadBuffer()'最後在'BufferNotEmpty'上睡覺?緩衝區已被使用,所以繼續前進並處理它。如果需要等待數據,讓下一次調用「ReadBuffer()」。爲什麼'WriteBuffer()'最後會在'BufferNotFull'上休眠。緩衝區已被寫入,所以繼續前進。如果需要等待消耗以釋放空間,讓下一次調用WriteBuffer()進入休眠狀態。你讓製片人和消費者彼此等待太久。另外,我認爲你需要喚醒變量,而你仍然在CS鎖內,而不是在外面。 –

回答

0

我認爲第一個問題是您在退出臨界區之後調用SleepConditionalVariableCS。

documentation for SleepConditionVariableCS

這個關鍵部分必須恰好一次調用者當時SleepConditionVariableCS輸入被調用。

documentation for LeaveCriticalSection描述,退出你沒有自己的臨界區導致的錯誤「可以使用EnterCriticalSection的無限期等待造成另一個線程」。

相關問題