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

时间:2015-08-06 23:48:58

标签: c++ multithreading debugging mutex

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

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 launched\n", "", "");
    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 event\n", "", "");           

    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 server\n")

    debug("End of FD_READ\n", "", "");

}
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

2 个答案:

答案 0 :(得分:1)

SendMessage阻塞,直到窗口处理消息。如果该窗口是在另一个也调用debug的线程上创建的,那么就会出现死锁。

答案 1 :(得分:1)

Brandon Kohn's answer是你陷入僵局的原因。至于解决方案,我建议您执行以下操作:

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();
    }
}