- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我已经实现了一个类,它允许我将线程与条件变量同步。关于 notify_all 应该在锁内还是在锁外完成,我发现了相互矛盾的信息。我找到了以两种方式构造的示例。
优先释放锁的说法是为了防止等待线程在被通知释放后立即阻塞在互斥体上。
反对首先释放锁的论点是等待线程可能会错过通知。
发布函数的两个版本在这里:
// version 1 - unlock then notify.
void release(int address = 1)
{
{
std::lock_guard<std::mutex> lk(_address_mutex);
_address = address;
}
_cv.notify_all();
}
// version 2 - notify then unlock
void release(int address = 1)
{
std::lock_guard<std::mutex> lk(_address_mutex);
_address = address;
_cv.notify_all();
}
供引用,等待代码如下所示:
bool wait(const std::chrono::microseconds dur, int address = 1)
{
std::unique_lock<std::mutex> lk(_address_mutex);
if (_cv.wait_for(lk, dur, [&] {return _address == address; }))
{
_address = 0;
return true;
}
return false;
}
在版本 1 中是否存在等待线程丢失通知的风险,其中允许互斥量在 notify_all 之前超出范围?如果是这样,它是如何发生的? (我不清楚这是如何导致错过通知的。)
我可以清楚地看到在通知期间保持互斥量锁定是如何导致等待线程立即进入等待状态的。但如果可以防止错过通知,这是一个很小的代价。
最佳答案
如果在条件测试状态更改和通知之间的某个时间间隔内持有互斥锁,则没有释放锁的风险。
{
std::lock_guard<std::mutex> lk(_address_mutex);
_address = address;
}
_cv.notify_all();
这里,互斥体在 _address
改变后被解锁。所以没有风险。
如果我们将 _address
修改为原子的,天真地这看起来是正确的:
{
std::lock_guard<std::mutex> lk(_address_mutex);
}
_address = address;
_cv.notify_all();
但事实并非如此;在这里,互斥量在修改条件测试和通知之间的整个期间被释放,
_address = address;
{
std::lock_guard<std::mutex> lk(_address_mutex);
}
_cv.notify_all();
然而,上面的内容再次变得正确(如果有点奇怪的话)。
风险在于条件测试将在互斥量处于事件状态(为假)的情况下进行评估,然后更改,然后发送通知,然后等待线程等待通知并释放互斥量。
waiting|signalling
lock
test
test changed
notification
listen+unlock
以上是错过通知的示例。
只要我们在测试更改之后和通知之前的任何地方持有互斥锁,它就不会发生。
关于c++ - condition_variable.notify_all 是否应该被互斥锁覆盖?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48958530/
此代码是实际项目代码的简化。主线程创建工作线程并使用 std::condition_variable 等待工作线程真正启动。在下面的代码中,std::condition_variable 在 curr
reference I'm using用以下方式解释这两者: wait_for "阻塞当前线程,直到条件变量被唤醒或在指定的超时时间之后" wait_until "阻塞当前线程,直到条件变量被唤醒或到
标题问题的较长版本是: On my machine, sizeof(std::condition_variable) is 72 bytes.What are these 72 bytes used
假设我有这样的事情: bool signalled = false; std::condition_variable cv; void thread1() { while (true) {
我在下面的代码中遇到错误。 recursive_mutex m_RecurMutex; condition_variable cond; unique_lock lock(m_RecurMutex);
这是什么: bool ready; boost::mutex mutex; boost::condition_variable cond; boost::unique_lock lock(mutex)
这个问题是关于condition_variable.wait()的功能。我认为它可能没有锁定 unique_lock当它被通知时立即。让我展示一下我的代码,您会更好地理解我的测试。 注意:编译器 g+
我是条件变量的新手,我想知道为什么计数器变量等于 99 之后的这段代码块?删除for循环并改用“counter += 99”使代码工作,它与sleep_for有什么关系吗?感谢您的帮助:) #incl
关闭。这个问题需要debugging details .它目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and th
似乎 condition_variable notify_one 并不总是按应有的方式工作。 struct Task { std::mutex mutex; std::conditio
条件变量可用于向其他线程发出信号,表明发生了某些事情: mutex m; condition_variable cv; thread t1([&cv]{ // processing .
没有 std::condition_variable 的应用程序: #include #include #include #include #include #include std::m
首先是我的代码,让我的解释更清楚: struct Foo { std::condition_variable cv; }; static Foo* foo; // dynamically cr
std::condition_variable::notify_one() 或 std::condition_variable::notify_all() 是否保证非原子内存写入当前线程之前该调用将在
我目前正在对并发队列进行编程,同时学习如何使用C++ 11的多线程功能。 当使用者调用dequeue()函数且队列中没有任何条目时,该函数应等待,直到另一个线程调用enqueue()为止。我正在为此使
我有一个关于notify_one函数的问题。在下面的代码中, #include #include #include #include #include std::condition_vari
我有一个以下类(class)- boost::condition_varaible cond_; 当我尝试编译时- [rmitra @ butterfly boost] $ make EXE = th
这是一个小代码段 request_ptr pop() { request_ptr rp; std::unique_lock lock(cv_mtx); auto time =
假设我有一个包含std::queue的ThreadQueue类,并且我将每个std::ref的实例传递给线程。进一步假设,线程1(主线程)创建并保存ThreadQueue对象,并将消息倒入其中,第二个
我有课,用 queue的 std::function成员和方法 Push和 Pop . 我要实现加法PushAndWaitUntilExecuted .当你有一个时很容易consumer-thread
我是一名优秀的程序员,十分优秀!