如何使一个线程按预期顺序多次等待另一个线程

时间:2019-01-11 08:52:24

标签: c++ multithreading

我是C ++多线程编程领域的新手。我想从磁盘上读取块数据并根据这些数据进行一些计算。为了简化代码,我编写了以下演示来测试我的想法。

读取数据的功能如下。

void read_value(std::vector<int> &data)
{
    for (int j = 1; j < 5; j++)
    {
        cv_m.lock();
        std::cout << "read data iteration is " << j << std::endl;

        for (int i = 0; i < 5; i++)
            data.at(i) = i * j;
        is_print = true;
        cv_m.unlock();
        cv.notify_one();
    }
}

在此函数中,我想读取4次数据,每次读取后,我想调用另一个名为print_value的函数来输出数据。 print_value功能在这里。

void print_value(const std::vector<int> &data)
{
    for (int j = 1; j < 5; j++)
    {
        std::unique_lock<std::mutex> lk(cv_m);
        std::cout << "waiting for output data" << std::endl;
        cv.wait(lk, []{return is_print;});
        for (int i = 0; i < data.size(); i++)
            std::cout << data[i] << std::endl;
        is_print = false;
    }
}

尽管我将print_value函数设置为等待4次,但是还有另一个问题。 read_value函数将不会等待print_value函数,它将仅读取4次数据。输出结果如下。

read data iteration is 1
read data iteration is 2
read data iteration is 3
read data iteration is 4
waiting for output data
0
4
8
12
16
waiting for output data
Program ended with exit code: 9

我知道两个线程互相等待非常危险。看来条件变量只能在一个线程等待另一个线程而不是我的情况下使用。这个问题有解决方案吗?

2 个答案:

答案 0 :(得分:0)

最后,我通过使用状态转换解决了这个问题。我设置了一个全局变量状态。当状态等于1时,线程1开始读取数据,线程2进入睡眠状态,直到状态变为2。在这种情况下,尽管CPU占用了更多资源,但是我可以成功地管理程序。

答案 1 :(得分:-1)

您还需要让read_value等待条件变量。请参见std::condition_variable中的the example code,以适合您的循环。

#include <iostream>
#include <string>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex m;
std::condition_variable cv;
bool read_ready = false;
bool print_ready = false;

void read_value(std::vector<int> &data)
{
    for (int j = 1; j < 5; j++)
    {
        // Wait until print_value is done with the previous data
        std::unique_lock<std::mutex> lk(m);
        cv.wait(lk, []{return read_ready;});

        std::cout << "read data iteration is " << j << std::endl;

        for (int i = 0; i < 5; i++)
            data.at(i) = i * j;
        print_ready = true;
        read_ready = false;
        lk.unlock();
        cv.notify_one();
    }
}

void print_value(const std::vector<int> &data)
{
    for (int j = 1; j < 5; j++)
    {
        std::lock_guard<std::mutex> lk(m);
        read_ready = true;
        lk.unlock();
        cv.notify_one();
        lk.lock();

        std::cout << "waiting for output data" << std::endl;
        cv.wait(lk, []{return print_ready;});
        for (int i = 0; i < data.size(); i++)
            std::cout << data[i] << std::endl;
        print_ready = false;
    }
}