user2260241
user2260241

Reputation: 95

notify_all does not wake up wait thread

DBThread::DBThread() : running_(false)
{

}

DBThread::~DBThread()
{
    if (thread_)
    {
        thread_->join();
    }
}

void DBThread::Init()
{
    thread_ = std::make_shared<std::thread>(std::bind(&DBThread::Run, this));
    std::unique_lock<std::mutex> lock(mutex_);
    cv_.wait(lock, [&] {return running_; });
    std::cout << "Init success";
}

void DBThread::AddTask(std::shared_ptr<Delegate> task)
{
    std::lock_guard<std::mutex> lock(mutex_);
    task_queue_.push(task);
}

void DBThread::Run()
{
    running_ = true;
    cv_.notify_all();
    while (true)
    {
        std::unique_lock<std::mutex> lock(mutex_);
        cv_.wait(lock, [&] {return !task_queue_.empty(); });
        std::cout << "run task" << std::endl;
    }
}

I have two threads,let's name it A and B,A call Init and wait for B to fully initialized, A sometimes hang on wait even if running_ is true.Any idea why this happens.Any help will be appreciated.

Upvotes: 2

Views: 1102

Answers (1)

evan
evan

Reputation: 1683

std::condition_variable::wait(lock, pred) is basically the same as

while (!pred()) {
    wait(lock);
}

If the thread sets running_ to true and calls notify_all() between the time that the predicate is checked, but before wait is called, then the notification will be lost, and the wait will wait until another notification comes. Easiest way to fix it is:

void DBThread::Run()
{
    std::unique_lock<std::mutex> lock(mutex_);
    running_ = true;
    cv_.notify_all();
    while (true)
    {
        cv_.wait(lock, [&] {return !task_queue_.empty(); });
        std::cout << "run task" << std::endl;
    }
}

Upvotes: 3

Related Questions