Multithreading 如何很好地同步?
给定以下C++11代码片段:Multithreading 如何很好地同步?,multithreading,c++11,mutex,condition-variable,Multithreading,C++11,Mutex,Condition Variable,给定以下C++11代码片段: #include <condition_variable> #include <mutex> std::mutex block; long count; std::condition_variable cv; void await() { std::unique_lock<std::mutex> lk(block); if (count > 0) cv.wait(lk); } void c
#include <condition_variable>
#include <mutex>
std::mutex block;
long count;
std::condition_variable cv;
void await()
{
std::unique_lock<std::mutex> lk(block);
if (count > 0)
cv.wait(lk);
}
void countDown()
{
std::lock_guard<std::mutex> lk(block);
if (count > 0)
{
count--;
if (count==0) cv.notify_all();
}
}
#包括
#包括
std::互斥块;
长计数;
std::条件变量cv;
无效等待()
{
std::唯一锁lk(块);
如果(计数>0)
cv.等待(lk);
}
无效倒计时()
{
标准:锁紧装置lk(块);
如果(计数>0)
{
计数--;
如果(计数=0)cv.notify_all();
}
}
如果不清楚我试图完成什么,我希望调用等待暂停调用线程,而计数大于0,如果它已经减少到零,那么它就不应该暂停。其他线程可能会调用countDown(),这将唤醒以前调用wait的所有线程
上面的代码似乎在我尝试过的所有情况下都能工作,但我对此有一个令人不安的疑问,因为在我看来,如果调用wait()的线程恰好在其条件测试被评估之后,线程被cv.wait()调用实际挂起之前立即被抢占,如果此时正在调用倒计时函数,且计数等于0,那么它将向条件变量发出通知,如果它实际上已经在等待它。。。但是调用wait的线程还没有到达cv.wait()调用,因此当调用wait的线程恢复时,它会在cv.wait()调用处停止并无限期地等待
实际上,我还没有在实践中看到这种情况发生,但我想针对可能发生的情况强化代码。考虑这些可能性是件好事。但在这种情况下,您的代码是正确和安全的 如果
wait
在其条件测试被评估后立即被抢占,并且就在cv.wait()调用实际挂起线程之前,如果此时正在调用倒计时函数,后一个线程将在尝试获取block
互斥时阻塞,直到wait
实际调用cv.wait(lk)
调用cv.wait(lk)
会隐式释放block
上的锁,因此现在另一个线程可以在倒计时()中获得block
上的锁。只要线程在countDown()
中持有block
上的锁(即使在调用cv.notify\u all()
之后,wait
线程也不能从cv.wait()
返回。wait
线程在从cv.wait()
更新
虽然
,但我在查看您的代码时确实犯了一个新手错误
cv.wait(lk)
可能会错误返回。也就是说,它可能会返回,即使它尚未得到通知。为了防止这种情况,您应该将wait
置于while循环下,而不是if:
void await()
{
std::unique_lock<std::mutex> lk(block);
while (count > 0)
cv.wait(lk);
}
void wait()
{
std::唯一锁lk(块);
而(计数>0)
cv.等待(lk);
}
现在,如果等待错误地返回,它将重新检查条件,如果仍然不满足,则再次等待。您最好考虑这些可能性。但在这种情况下,您的代码是正确和安全的
如果wait
在其条件测试被评估后立即被抢占,并且就在cv.wait()调用实际挂起线程之前,如果此时正在调用倒计时函数,后一个线程将在尝试获取block
互斥时阻塞,直到wait
实际调用cv.wait(lk)
调用cv.wait(lk)
会隐式释放block
上的锁,因此现在另一个线程可以在倒计时()中获得block
上的锁。只要线程在countDown()
中持有block
上的锁(即使在调用cv.notify\u all()
之后,wait
线程也不能从cv.wait()
返回。wait
线程在从cv.wait()
更新
虽然
,但我在查看您的代码时确实犯了一个新手错误
cv.wait(lk)
可能会错误返回。也就是说,它可能会返回,即使它尚未得到通知。为了防止这种情况,您应该将wait
置于while循环下,而不是if:
void await()
{
std::unique_lock<std::mutex> lk(block);
while (count > 0)
cv.wait(lk);
}
void wait()
{
std::唯一锁lk(块);
而(计数>0)
cv.等待(lk);
}
现在,如果等待错误地返回,它将重新检查条件,如果仍然不满足,则再次等待。亲爱的上帝,这是一个错误。有人入侵了Howard的StackOverflow帐户,天哪,是个错误。有人侵入了Howard的StackOverflow帐户。