我有一个多线程代码访问有限的资源(最大并发线程数由max_accesses
定义)。该资源可以从代码的几个部分使用,所以我必须提供一个工具来计算和管理访问。
目前,我用下面的方法来做,但我发现在一些随机的情况下会出现死锁:有时候,condition_variable等待,没有人来唤醒它,因为所有的访问线程在决定等待和有效等待之间释放。
我不习惯使用条件变量,我不知道如何修改我的过程来避免这种死锁。我没有一个测试能够以很大的概率重现这个bug。我宁愿在这里寻求帮助,然后避免其他潜在的bug。
std::mutex mutex_counter;
std::mutex mutex_wait;
std::condition_variable cv_wait;
std::size_t num_accesses = 0;
std::size_t max_accesses = 8;
bool acquire()
{
{
std::lock_guard<std::mutex> lock_counter(mutex_counter);
if(num_accesses < max_accesses)
{
++num_accesses;
return true;
}
// If I'm here, the maximum number of accesses is reached, I have to wait
}
std::unique_lock<std::mutex> lock_wait(mutex_wait);
while(true)
{
{
std::lock_guard<std::mutex> lock_counter(mutex_counter);
if(num_accesses < max_accesses)
{
++num_accesses;
return true;
}
}
// Sometimes, here num_accesses == 0, because all the accesing threads just released
// Then it's an infinite wait because there is no remaining thread to notify
cv_wait.wait(lock_wait);
}
}
bool release()
{
std::lock_guard<std::mutex> lock_counter(mutex_counter);
assert(num_accesses > 0);
--num_accesses;
cv_wait.notify_all();
}
1条答案
按热度按时间yb3bgrhw1#
FYI:这个问题有一个名字,它被称为“丢失通知”。您可以通过使用 * 相同的互斥对象 * 作为计数器 * 和 * 作为“等待”来防止它: