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

 

posted @ 2020-03-04 19:09  雪域蓝心  阅读(934)  评论(0编辑  收藏  举报