C++ 在一个线程中修改成员变量并在另一个线程中读取

C++ 在一个线程中修改成员变量并在另一个线程中读取,c++,pthreads,C++,Pthreads,我有两个成员变量 class MessageQueues { .... char* m_InputBuffer; uint32_t m_InputBufferSize; .... }; 我正在当前线程中的函数中更新它们,并使用调试器查看是否更新了成员变量。但在另一个函数中,在单独的线程中运行,成员变量包含垃圾 因此,我有一个函数,它读取两个值并将它们写入两个成员变量,完成后触发另一个线程 ErrorCode MessageQueue::handleIncomin

我有两个成员变量

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()函数中锁定互斥体。通过调试器,互斥锁被锁定,但成员变量包含垃圾。好的,我想我应该对此进行调查。

这里有几个错误:

  • 当互斥锁被锁定时,必须等待条件变量。文档是必须阅读的
  • 条件变量必须由
    while
    循环处理
  • 修正:

    class MessageQueues {
        ....
        char* m_InputBuffer;
        uint32_t m_InputBufferSize;
        uint32_t m_WriteGeneration = 0; // <--- a fix.
        uint32_t m_ReadGeneration = 0;  // <--- a fix.
        ....
    };
    
    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;
        ++m_WriteGeneration; // <--- a fix.
        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_mutex_lock(&mutexMsgQueueIncoming);  // <--- a fix.
            while(m_ReadGeneration == m_WriteGeneration) // <--- a fix.
                pthread_cond_wait(&msgQueueCondition, &mutexMsgQueueIncoming); // <--- a fix.
            m_ReadGeneration = m_WriteGeneration; // <--- a fix.
            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;
    }
    
    class消息队列{
    ....
    char*m_输入缓冲区;
    uint32\u t m\u输入缓冲区大小;
    
    uint32_t m_WriteGeneration=0;//您在第一块代码中锁定在哪里?有解锁,但没有锁定?请提供@JoeyMallone是否有可能在两个线程中mutexmssgqueueincoming不同?可能是某些类副本构造函数具有不同的初始化互斥体?您是否尝试通过ugh它的指针,来自两个线程,而不是通过值传递它?如果在第二个块中有一个虚假的唤醒呢?它是如何重新等待的?@huseyintugrulbuyukisik,好的,让我调查一下。谢谢你的想法/提示。@Joey也许有一天!哎哟,谢谢。我误解了如何使用,pthread_cond__wait()然后。午饭后让我测试一下。可能是错误。我应该更熟悉pthread库。谢谢。p.s。我不能使用C++11。我不能使用Boost。我被困在1998年了P@JoeyMallone1998年你可以使用Boost。哦,我的天哪!哦,那我甚至不在1998年!我不能使用Boost。这不是我的选择。这不是我的选择。@JoeyMallone在pthread原语上制作精简包装器,然后为您执行错误检查。