2015-07-03 27 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的无限期等待造成另一个线程”。

相关问题