C/C++ 和其他语言中的条件变量使用模式

Posted

技术标签:

【中文标题】C/C++ 和其他语言中的条件变量使用模式【英文标题】:Condition variable usage pattern in C/C++ and other languages 【发布时间】:2015-12-08 20:07:20 【问题描述】:

如果您查看描述条件变量 (cv) 用法的文档,您会看到例如在 PThreads 和 C++ 中,您无需持有 cv 的互斥锁即可在此 cv 上调用 notify。而例如在 Java 和 Python 中,您必须锁定互斥体才能执行相同的操作。

考虑到像 Java 这样的语言的实现最终会使用一些本机线程工具,是否有一些深层原因为什么会以这种方式实现(我是关于后一种情况)?

【问题讨论】:

可能它不是在 pthreads 之上实现的 .. 但这只是一个假设。我觉得这个问题在cs.stackexchange.com 上可能会得到更好的(甚至任何)答案... 显然 JVM 可以这样实现它,但它犯了一个常见的错误,我见过很多很多人在 c++ 中以相当低的成本做的可能性很小(你需要持有一个锁有点长,但就是这样) @Voo 错误是在修改条件所依赖的数据时没有持有互斥锁? @vehsakul 检查条件(这通常取决于正在修改的数据)而不持有锁。是的,在某些情况下这是完全有效的,但它为错误创造了很大的机会。托管语言归根结底都是关于交易性能的选项以确保安全。我个人认为这里的权衡是合理的,我不认为有很多现实生活中的例子会产生很大的不同。 @Voo 好的,您关于安全与性能的观点很明确。 【参考方案1】:

Java notifynotifyAll 基本同步工具都要求您在调用它们之前对对象进行同步。这是为了一个简单的安全点,因为它还要求您在 waiting 之前同步它们。

例如,如果您有两个线程。一个线程从缓冲区读取数据,一个线程将数据写入缓冲区。

读数据线程需要等到写数据线程完成将一个数据块写入缓冲区,然后才能读取该块。

如果 wait()notify()notifyAll() 方法可以在不同步的情况下调用,那么您可以获得一个竞争条件:

读取线程调用wait(),线程被加入等待队列。

同时,写入线程调用notify()表示已添加数据。

读取线程错过了更改并永远等待,因为notify()wait() 之前被处理。

通过强制 waitnotify 在同步块内发生,可以消除这种竞争条件。

【讨论】:

以上是关于C/C++ 和其他语言中的条件变量使用模式的主要内容,如果未能解决你的问题,请参考以下文章

C++ 条件变量使用详解

使用条件变量超时的读取器/写入器锁定

使用条件计算变量并打印所有最终值

HaskellHaskell中的条件编译

React学习:条件渲染

如何设置条件编译变量?