【发布时间】:2018-09-07 09:39:57
【问题描述】:
我有两个成员变量。
class MessageQueues {
....
char* m_InputBuffer;
uint32_t m_InputBufferSize;
....
};
我在当前线程的函数中更新它们,甚至使用调试器查看成员变量已更新。但是在另一个函数中,在单独的线程中运行,成员变量包含垃圾。
所以,我有一个函数,它读取两个值并将它们写入两个成员变量,并在完成后触发另一个线程。
ErrorCode MessageQueue::handleIncomingMessage(char receiveBuffer[], const uint32_t bufferSize) {
ES_TRC3("started");
ErrorCode errorCode = ES_SUCCESS;
pthread_mutex_lock(&mutexMsgQueueIncoming);
m_InputBuffer = receiveBuffer;
m_InputBufferSize = bufferSize;
ES_TRC3("triggering and unlocking");
pthread_cond_signal(&msgQueueCondition);
pthread_mutex_unlock(&mutexMsgQueueIncoming);
ES_TRC3("triggered and unlocked");
return errorCode;
}
然后在第二个成员函数中,它无限期地在单独的线程中运行并等待消息,
ErrorCode MessageQueue::runReceiver(void) {
ES_TRC3("started");
ErrorCode errorCode = ES_SUCCESS;
while(true)
{
ES_TRC3("waiting for input messages");
pthread_cond_wait(&msgQueueCondition, &mutexMsgQueueIncoming);
pthread_mutex_lock(&mutexMsgQueueIncoming);
ES_TRC3("will parse message");
if (strlen(m_InputBuffer) > 0UL) {
if ((errorCode = m_MsgProtocol->parseMessage(m_InputBuffer, m_InputBufferSize)) != ES_SUCCESS)
{
ES_TRC1("failed to parseMessage, error:%d", errorCode);
}
}
ES_TRC3("message parsed");
pthread_mutex_unlock(&mutexMsgQueueIncoming);
}
return errorCode;
}
使用调试器(以及日志消息),我可以看到变量的更新和触发以正确的顺序发生。所以我不明白为什么在第二个函数中,成员变量似乎不包含正确的值。我在某处读到了一些关于“易失性”的东西。但不要真的认为,这是正确的答案。我在这里做错了吗?
更新: 互斥锁在类之外,但在同一个源文件中,在顶部初始化,如下所示。
pthread_mutex_t mutexMsgQueueIncoming = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t msgQueueCondition = PTHREAD_COND_INITIALIZER;
其实很奇怪。当我在没有调试器的情况下运行程序时,似乎无法在 runReceiver() 函数中锁定互斥锁。使用调试器,互斥锁被锁定,但成员变量包含垃圾。好的,我想我应该调查一下。
【问题讨论】:
-
你在哪里锁定第一块代码?有解锁但没有锁定?
-
@JoeyMallone 是否有可能 mutexMsgQueueIncoming 在两个线程中不同?也许某些具有不同初始化互斥锁的类复制构造函数?您是否尝试过从两个线程通过其指针访问类实例,而不是通过值传递它?此外,如果在第二个街区出现虚假唤醒怎么办?它如何重新等待?
-
@huseyintugrulbuyukisik,好的,让我调查一下。感谢您的想法/提示。
-
@Joey 也许有一天!