我自己写了一个线程池,Result类用于获取线程池任务的计算结果。最初,我使用简单的信号量机制来实现线程同步。代码如下:
void Semaphore::wait() {
std::unique_lock<std::mutex> lock(mutex_);
condition_.wait(lock, [&] { return count_ > 0; });
--count_;
}
void Semaphore::signal() {
std::unique_lock<std::mutex> lock(mutex_);
++count_;
condition_.notify_all();
}
Any Result::get() {
if (!isValid_)
return "";
sem_.wait();
return std::move(any_);
}
void Result::setAny(Any any) {
this->any_ = std::move(any);
sem_.signal();
}
get()方法用于获取线程池中任务的计算结果。如果计算没有完成,get()将会被阻塞。线程池中调用setAny来存储任务的计算结果。
后来我想是否可以直接使用锁和condition_variables来实现同步,然后就放弃了Semaphore类,直接在get()和setAny()中使用锁和条件变量,但是发现线程会被阻塞当最后调用 get() 时。这是为什么?
顺便说一句,如果线程池中只有一个线程,程序可以顺利执行;但如果线程数大于1,并且任务数大于1,就会出现上述问题。代码如下:
Any Result::get() {
if (!isValid_)
return "";
std::unique_lock<std::mutex> lock(mtx);
cd.wait(lock);
return std::move(any_);
}
void Result::setAny(Any any) {
this->any_ = std::move(any);
cd.notify_one();
}
您所看到的很可能是虚假唤醒。等待条件变量可能会毫无理由地被虚假中断,您永远不应该在没有谓词的情况下等待条件变量。