Reputation: 95
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
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