惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
V
V2EX
WordPress大学
WordPress大学
U
Unit 42
I
InfoQ
A
About on SuperTechFans
宝玉的分享
宝玉的分享
J
Java Code Geeks
博客园 - 司徒正美
爱范儿
爱范儿
Engineering at Meta
Engineering at Meta
G
Google Developers Blog
人人都是产品经理
人人都是产品经理
小众软件
小众软件
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
aimingoo的专栏
aimingoo的专栏
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Last Week in AI
Last Week in AI
腾讯CDC
Recent Announcements
Recent Announcements

OhYee 博客

小鹏辅助驾驶测评|OhYee 博客 小鹏非支持手机开启自动解锁|OhYee 博客 使用函数计算实现 301 重定向|OhYee 博客 针对 HTML 内容使用 Ant Design 图片弹框|OhYee 博客 博客进程泄露及僵尸进程解决|OhYee 博客 蓝易云服务器体验|OhYee 博客 SSH 调起本地 VSCode|OhYee 博客 【2022 秋招内推】阿里云后端研发工程师|OhYee 博客 使用函数计算获取 IP 地址信息|OhYee 博客 正确获取客户端 IP/HTTP Header 也可能重复|OhYee 博客 评测 Oculus Quest2 及 BigScreen|OhYee 博客 NextJS 热重载保留状态|OhYee 博客 如何优雅地贴 gist 代码|OhYee 博客 Linux 精细化文件权限|OhYee 博客 VSCode 容器开发环境|OhYee 博客 Clash 的不兼容更新排查|OhYee 博客 Zeek 导出 PCAP|OhYee 博客 记一次 ssh 配置问题|OhYee 博客 Git Commit 规范化工具|OhYee 博客 谈谈《星之卡比-探索发现》|OhYee 博客 VSCode 快捷键绑定 Shell 命令|OhYee 博客 ASN.1 语法及 X.509 证书格式解析解析|OhYee 博客 腾讯企业邮箱忽略 MX 记录发信|OhYee 博客 Chrome/Edge 标签组插件|OhYee 博客 【应届内推】阿里云后端研发工程师|OhYee 博客 损坏的 Typecho 备份处理为 JSON|OhYee 博客 VS Code VIM 插件高效使用|OhYee 博客 SSH 正反向代理|OhYee 博客 Let's Encrypt 根证书过期引发的问题|OhYee 博客 OpenWRT 忽略内核依赖|OhYee 博客
pthread 的条件变量|OhYee 博客
2020-03-05 · via OhYee 博客

pthread 的条件变量 pthread_cond 的使用

这是一篇最后编辑于 6 年前 的文章,其内容可能与目前实际情况差异较大,请注意甄别

pthread 的条件变量

通常而言,阻塞一个线程要使用互斥锁 mutex ,但是在特别情况下则可能需要别的选择
比如,当需要等一个线程的中间执行结果时,如果使用互斥锁,那么只能写一个无限循环,并且在循环内不断加锁、解锁,这显然是一个很不优雅的写法

这时可以使用条件变量pthread_cond来解决这个问题

在一个线程调用int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex);阻塞该线程,直至条件满足
而在工作线程中,则使用int pthread_cond_signal(pthread_cond_t *cv);通知阻塞的线程继续执行

这里的pthread_cond_tpthread_mutex_t本质上都是一个锁,可以看作是在 A 线程阻塞,当 B 线程执行结束后解锁该锁,从而使得 A 线程继续执行

pthread_cond_wait

int pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex);会阻塞当前线程,等待其他线程的回应
需要注意的是,这个函数执行结束不代表条件一定满足条件,因为条件变量本身也只是一个锁,并不存在任何判断。同时在多核处理器中,也有可能因为各种问题解锁条件变量1。因此,必须在阻塞的线程上判断条件是否符合,也即阻塞的部分应该类似这个样子:

pthread_mutex_lock(&mutex);
while (ok) {
    pthread_cond_wait(&cv, &mutex);
}
pthread_mutex_unlock(&mutex);

在这里,因为需要在多个进程中都需要对判断的条件涉及的变量进行读写,因此需要使用一个单独的互斥锁对其进行保护。
这也是为什么阻塞函数必须要传入一个互斥锁:需要一个互斥锁对判断条件进行保护2 3

而这个阻塞函数本身要完成的任务如下:

  1. 释放互斥锁,以供子线程中使用
  2. 将条件变量锁加入到队列中,等待触发
  3. 条件变量锁触发,给互斥锁加锁

pthread_cond_signal 和 pthread_cond_broadcast

int pthread_cond_signal(pthread_cond_t *cv);会发送信号,解锁该条件变量阻塞的一个线程(具体顺序看调用队列)
int pthread_cond_broadcast(pthread_cond_t *cv);会发送信号,解锁该条件变量阻塞的所有线程

如果cv对应的条件变量并没有阻塞线程,那么该函数效果相当于没有执行

同时,通常情况而言,调用该函数前需要判断一个条件是否满足,因此对于该条件需要加锁,并且需要是阻塞的线程传入的互斥锁。但是在实际使用中,如果这个条件涉及的变量只在阻塞的线程和工作线程中用到,那么实际上在工作线程里判断条件没有必要加锁4。当然,加了除了可能会影响性能也没有别的问题

参考资料


  1. Linux下Condition Vairable和Mutext合用的小细节 ↩︎

  2. 为什么pthread_cond_wait需要互斥锁mutex作为参数 ↩︎

  3. pthread_cond_wait 为什么需要传递 mutex 参数? ↩︎

  4. 详解linux互斥锁 pthread_mutex和条件变量pthread_cond ↩︎