为什么既有std :: condition_variaible的通知和等待功能,都需要锁定的静音
Why do both the notify and wait function of a std::condition_variable need a locked mutex
在我永远无法理解std::contion_variable
s的任务中,我遇到了以下内容。在此页面上说:
void print_id (int id) {
std::unique_lock<std::mutex> lck(mtx);
while (!ready) cv.wait(lck);
// ...
std::cout << "thread " << id << 'n';
}
之后,它说了:
void go() {
std::unique_lock<std::mutex> lck(mtx);
ready = true;
cv.notify_all();
}
现在,据我了解,这两个功能都会停止在std::unqique_lock
行上。直到获得唯一的锁。也就是说,没有其他线程有锁定。
因此,请首先执行print_id
功能。唯一的锁将是aquired的,功能将在等待线上停止。
然后执行go
函数(在单独的线程上),则该代码将停止在唯一的锁线上。由于MUTEX已被print_id
函数锁定。
显然,如果代码是这样,这将行不通。但是我真的看不到我没有到达什么。所以请启发我。
所缺少的是 wait
解锁互斥,然后在 cv
上等待信号。
它在返回之前再次锁定二线。
您可以通过单击在找到示例的页面上的等待来找到这一点:
在阻止线程的时刻,该功能会自动调用lck.unlock(),允许其他锁定线程继续。
曾经通知(明确地通过某些线程明确),该功能解开并调用lck.lock(),将LCK与调用函数时的状态相同。
您错过了一点点;呼叫 wait()
unlocks the mutex。线程在原子上(释放二线 入睡)。然后,当信号唤醒时,它试图重新接触静音(可能阻止);一旦获取它,就可以继续。
请注意,不必将MUTEX锁定用于调用notify_*
,仅适用于wait*
要回答提出的问题,这对于您不应出于绩效原因而不应锁定通知的说法似乎是必要的(不是比绩效重要吗?):锁定"等待",并始终锁定"通知"的建议是保护用户免受数据和逻辑种族的侵害。如果没有" GO"锁定,您发布的程序将立即在"准备就绪"上进行数据竞赛。但是,即使准备就绪即使已经同步(例如原子),您也会有一场逻辑竞赛,没有错过的通知,因为如果没有" go"中的锁 检查"就绪"和的检查 原子变量本身上的同步不足以防止这种情况。这就是为什么赫尔格林德在不握住锁的情况下通知时会警告的原因。在某些有一些边缘案例中,实际上不需要静音锁定。在所有这些情况下,都需要事先进行双向同步,以便生产线程可以确保其他线程已经在等待。IMO这些案件仅适用于专家。实际上,我已经看到一位专家,谈论了多线程,弄错了 - 他认为原子柜台就足够了。也就是说,等待始终是正确性的(或至少是一个与等待的原子能的操作),这就是为什么标准库强制执行它并在输入等待时解锁Mutex的原因。p> POSIX条件变量与Windows事件不同,而不是"愚蠢的",因为它们是无状态的(除了了解等待线程外)。在那里使用锁定的锁定的建议是保护您免受最严重和最常见的螺丝钉的侵害。您可以使用Mutex 条件var bool变量构建类似Windows的状态事件,如果您愿意。
- 在执行其他功能的同时播放动画(LED矩阵和Arduino/ESP8266)
- 多态性和功能结合
- 带内存和隔离功能的SQLite
- 如何找到锁定Linux futex的C++行
- G锁定铸造到基础上会释放模拟行为
- 在CMakeLists.txt的安装功能中使用.cmake文件有什么用
- 类模板的成员功能的定义在单独的TU中完全专业化
- 有没有一种方法可以创建一个带有哈希表的数据库,该哈希表具有恒定时间查找功能
- 如何在C++中获得"静态纯虚拟"功能?
- 两个文件使用彼此的功能-如何解决
- 我应该实现右值推送功能吗?我应该使用std::move吗
- QML按钮点击功能执行顺序
- 如何检查线程是否锁定
- 无法理解此 return 语句的功能,没有它就会发生运行时错误
- 如果其对象在多个线程中运行,我们是否需要锁定类成员功能
- 为什么既有std :: condition_variaible的通知和等待功能,都需要锁定的静音
- 我应该如何在一个功能中锁定wxMutex,并在另一个功能中将其解锁
- boost中是否有允许写偏锁定的功能
- QtCore,QMutex 类,锁定功能 - 堆栈溢出故障
- 我创建锁定文件的功能导致访问冲突