测试多个线程在队列中的condition_variables上等待

时间:2017-02-10 03:06:54

标签: c++ multithreading condition-variable

我正在测试如何推送等待队列中condition_variables的对象。我想按照我的意愿执行线程,因为它们将在以后的关键部分中执行。什么都没有从线程中打印出来,这可能是错的?

mutex print_mu;

void print(function<void()> func)
{
    lock_guard<mutex> lock(print_mu);
    func();
}

unsigned int generate_id()
{
    static unsigned int id = 1;
    return id++;
}

class foo
{
    unsigned int id_;
    mutex mu_;
    condition_variable cv_;
    bool signal_;
    bool& kill_;
public:
    foo(bool kill) 
        :kill_(kill) 
        , signal_(false)
        , id_(generate_id())
    {
        run();
    }

    void set()
    {
        signal_ = true;
    }

    void run()
    {
        async(launch::async, [=]()
        {
            unique_lock<mutex> lock(mu_);
            cv_.wait(lock, [&]() { return signal_ || kill_ ; });

            if (kill_)
            {
                print([=](){ cout << " Thread " << id_ << " killed!" << endl; });
                return;
            }

            print([=](){ cout << " Hello from thread " << id_ << endl; });
        });
    }
};

int main()
{
    queue<shared_ptr<foo>> foos;
    bool kill = false;

    for (int i = 1; i <= 10; i++)
    {
        shared_ptr<foo> p = make_shared<foo>(kill);
        foos.push(p);
    }
    this_thread::sleep_for(chrono::seconds(2));

    auto p1 = foos.front();
    p1->set();
    foos.pop();

    auto p2 = foos.front();
    p2->set();
    foos.pop();

    this_thread::sleep_for(chrono::seconds(2));

    kill = true; // terminate all waiting threads unconditionally

    this_thread::sleep_for(chrono::seconds(2));

    print([=](){ cout << " Main thread exits" << endl; });

    return 0;
}

1 个答案:

答案 0 :(得分:1)

当一个线程调用std::condition_variable::wait时,它将阻塞,直到另一个线程在同一个notify_one上调用notify_allcondition_variable。由于您从未在任何notify_*上致电condition_variables,因此他们将永久阻止。

您的foo::run方法也将永久阻止,因为std::future的析构函数将阻止等待std::async调用的结果,如果它是引用该结果的最后std::future 。因此,您的代码死锁:您的主线程被阻塞,等待您的异步未来完成,并且您的异步未来将被阻止,等待主线程发出cv_信号。

(另外foo::kill_是一个悬空参考。好吧,如果run无论如何都会返回它。)