STL 条件变量 std :: condition_variable ->死锁
以下代码:
// 推送条件变量 std::mutex g_cvMutexPush; std::condition_variable g_cvPush; std::unique_lock <std::mutex> g_lkPush(g_cvMutexPush); // 唤醒推送 std::mutex g_cvMutexWakePush; std::condition_variable g_cvWakePush; std::unique_lock <std::mutex> g_lkWakePush(g_cvMutexWakePush); void PushHqThread(void* arg) { while (1) { // 取得行情数据 g_cvPush.wait(g_lkPush, [=](){return (0 == g_nPushThreadFinishFlag[nThreadIndex]); });
g_nPushThreadFinishFlag[nThreadIndex] = 1;
printf("123\n");
g_cvWakePush.notify_one(); } } // 唤醒其他线程 void NotifyOtherWaitThread() { // 所有线程推送完成的条件变量 g_cvWakePush.wait(g_lkWakePush, []() { bool ret = true; for (int i = 0; i < g_nPushHqThreadNum; i++) { ret &= (1 == g_nPushThreadFinishFlag[i]); } return ret; }); printf("......g_cvWakePush.wait end\n"); // 设置推送标志 for (int i = 0; i < g_nPushHqThreadNum; i++) { g_nPushThreadFinishFlag[i] = 0; } // 唤醒所有等待在这个条件变量上wait g_cvPush.notify_all(); }
其中有 10个 PushHqThread 线程 和 1个 NotifyOtherWaitThread线程。
有以下问题:
程序运行一段时间,PushHqThread 线程中, g_cvPush.wait(g_lkPush, [=](){return (0 == g_nPushThreadFinishFlag[nThreadIndex]); }); 代码中 wait 函数不一定成功,
那么, g_nPushThreadFinishFlag[i] 就不可能全部等于1,那么 NotifyOtherWaitThread中的
g_cvWakePush.wait
会一直等待,形成死锁的状态。找到原因,条件变量信号丢失导致。
想到的方法如下【未测试】:
// 推送条件变量 std::mutex g_cvMutexPush; std::condition_variable g_cvPush; std::unique_lock <std::mutex> g_lkPush(g_cvMutexPush); // 唤醒推送 std::mutex g_cvMutexWakePush; std::condition_variable g_cvWakePush; std::unique_lock <std::mutex> g_lkWakePush(g_cvMutexWakePush); bool g_nFlag = true; void PushHqThread(void* arg) { while (1) { while (g_nFlag) { g_cvPush.wait(g_lkPush, [=](){return (0 == g_nPushThreadFinishFlag[nThreadIndex]); }); } g_nPushThreadFinishFlag[nThreadIndex] = 1; printf("123\n"); g_cvWakePush.notify_one(); } } // 唤醒其他线程 void NotifyOtherWaitThread() { // 所有线程推送完成的条件变量 g_cvWakePush.wait(g_lkWakePush, []() { bool ret = true; for (int i = 0; i < g_nPushHqThreadNum; i++) { ret &= (1 == g_nPushThreadFinishFlag[i]); } return ret; }); printf("......g_cvWakePush.wait end\n"); g_nFlag = true; // 设置推送标志 for (int i = 0; i < g_nPushHqThreadNum; i++) { g_nPushThreadFinishFlag[i] = 0; } g_nFlag = false; // 唤醒所有等待在这个条件变量上wait g_cvPush.notify_all(); }