c++多线程调用函数问题

C++ multiple threads calling function issue

本文关键字:问题 函数 调用 多线程 c++      更新时间:2023-10-16

这段代码需要一些帮助。我创建了一个函数来在我的应用程序中打印一些调试文本("debug"函数)。2个线程(FD_READ和incDataProcess)正在使用这个函数在调试窗口内打印一些信息。当我运行以下代码时,数据显示不好,可能是因为2个线程同时访问函数(数据竞争)。当我尝试使用互斥锁一次限制一个线程对函数的访问时,程序会挂起。我不明白为什么当我用互斥锁保护函数时程序会挂起。我的互斥锁怎么了?

static mutex printMutex;
static mutex readQueueMutex;
//....
void debug(LPSTR text1, LPSTR text2, LPSTR text3)
{       
// printMutex.lock(); // the combination of lock - unlock 
//                       makes the program hang (solution 1)
//  lock_guard<mutex>_(printMutex); // Solution 2, the program
//                                     hangs also   
    char *Text1 = text1;
    char *Text2 = text2;
    char *Text3 = text3;
    char Text[2048];
    strcpy_s(Text, Text1);
    strcat_s(Text, Text2);
    strcat_s(Text, Text3);
    int TextLen = SendMessage(hDebug, WM_GETTEXTLENGTH, 0, 0);
    SendMessage(hDebug, EM_SETSEL, (WPARAM)TextLen, (LPARAM)TextLen);
    SendMessage(hDebug, EM_REPLACESEL, FALSE, (LPARAM)Text);
//  printMutex.unlock(); // See comment solution 1  
}
//.....
void incDataProcess(void *pBuffer)
{   
    debug("incDataThread launchedn", "", "");
    for(;;)
    {
        while (!readQueue.empty())
        {
            readQueueMutex.lock();
            string sReadBuffer = readQueue.front(); 
            readQueue.pop(); 
            readQueueMutex.unlock();
            string var;
            char *pVar = nullptr;                   
            char *next_token = nullptr;
            istringstream iss(sReadBuffer); // Put into a stream            
            while (getline(iss, var)) // Default delimiter 'n'
            {       
                pVar = _strdup(var.c_str()); // Cast string to char *                   
                if( strstr(pVar, "Qh57=") != NULL)
                {
                    char *label = strtok_s(pVar, "=", &next_token);     
                    char *pFoFd = strtok_s(NULL, "n", &next_token);                            
                    strcpy_s(foFd, pFoFd);
                    debug("Qh57=", foFd, "n");         
                }
            } //while getline
        } // while queue is not empty
    } // infinite for loop
}
//.....
case FD_READ:
{                       
    debug("FD_READ eventn", "", "");           
    int bytes_recv = recv(Socket, readBuffer, sizeof(readBuffer), 0);
    readQueueMutex.lock();
    readQueue.push(readBuffer);                     
    readQueueMutex.unlock();            
    char bytes[256];
    _itoa_s(bytes_recv, bytes, 10); 
    debug("Received ", bytes, " bytes from servern")
    debug("End of FD_READn", "", "");
}
break;

下面是没有同步的调试窗口:

FD_READ event
Received 8 bytes from server
End of FD_READ
Qh57=0
FD_READ eventReceived 49 bytes from serverEnd of FD_READ // Display problem
                                                         // when second 
                                                         // thread calls the function
FD_READ event
Received 127 bytes from server
End of FD_READ
FD_READ event
Received 57 bytes from server
End of FD_READ
Qh57=1

Brandon Kohn的答案是你陷入僵局的原因。作为解决方案,我建议您做以下事情:

static std::queue<std::string> pendingDebugMessages;
void debug(LPSTR text1, LPSTR text2, LPSTR text3)
{       
    lock_guard<mutex>_(printMutex);
    pendingDebugMessages.push(std::string());
    std::string& finalString = pendingDebugMessages.back();
    finalString = text1;
    finalString += text2;
    finalString += text3;
}
// Call this regularly from your message pump thread
void PrintPendingMessages()
{
    lock_guard<mutex>_(printMutex);
    while(!pendingDebugMessages.empty())
    {
        int TextLen = SendMessage(hDebug, WM_GETTEXTLENGTH, 0, 0);
        SendMessage(hDebug, EM_SETSEL, (WPARAM)TextLen, (LPARAM)TextLen);
        SendMessage(hDebug, EM_REPLACESEL, FALSE, (LPARAM)pendingDebugMessages.front().c_str());
        pendingDebugMessages.pop();
    }
}

SendMessage阻塞,直到窗口处理消息。如果该窗口是在另一个也调用debug的线程上创建的…僵局。