蔚淦丞
发布于 2026-09-08 / 8 阅读
0
0

Linux 线程等待 / 唤醒相关函数整理

线程间

一、pthread 条件变量族(pthread_cond_*)

头文件:#include <pthread.h>

表格

函数

作用

是否必须 mutex

说明

pthread_cond_wait(cond, mutex)

阻塞等待被唤醒;无限等待

必须预先持有 mutex

调用时原子释放锁休眠;被唤醒返回前重新获取锁;会遭遇虚假唤醒;只能被 pthread_cond_signal / pthread_cond_broadcast 唤醒

pthread_cond_timedwait(cond, mutex, abstime)

带超时的条件等待;超时自动返回

✅必须预先持有 mutex

abstime绝对时间(不是相对时间)。超时返回错误码ETIMEDOUT;同样会虚假唤醒

pthread_cond_signal(cond)

唤醒至少一个正在 cond_wait 的线程

❌不强制拿锁

没有线程在等待,则唤醒直接丢失,不会保存事件

pthread_cond_broadcast(cond)

唤醒全部正在 cond_wait 的线程

❌不强制拿锁

全部线程唤醒后去竞争 mutex,产生惊群

⚠注意:没有 pthread_wait() 这个函数,你脑子里的 wait,全称就是 pthread_cond_wait,没有单独的 wait。


二、简单睡眠函数(线程自己睡,外部不能主动提前唤醒

头文件:#include <unistd.h> / <time.h>

表格

函数

作用

说明

sleep(unsigned int seconds)

线程休眠多少秒

不需要

只能等到时间结束;别的线程无法提前叫醒它

usleep(useconds_t usec)

微秒级睡眠

不需要

已经废弃,不推荐使用

nanosleep(const struct timespec *req, struct timespec *rem)

高精度睡眠(秒 + 纳秒)

不需要

可被信号打断;rem 保存剩余未睡时间;外部线程不能主动唤醒,只能等时间到或者收到信号

重点:sleep /nanosleep,别的线程没有 API 可以中途叫醒它。只能等时间跑完,或者进程收到信号。 如果你需要「别的线程可以随时叫醒正在睡觉的线程」,sleep 系列做不到。


三、Linux IO 方式等待(eventfd + poll /epoll/select)

这是另一套完全独立体系,不使用 pthread_cond,不需要 mutex。 适合:单纯做 “事件通知、唤醒线程”,没有共享业务条件。

  1. eventfd() 创建一个事件 fd

  2. 等待线程:poll() / epoll_wait() / select() 阻塞等待 eventfd 可读

  3. 其他线程:向 eventfd 执行write(),等待线程立刻被唤醒。

表格

函数

作用

特点

eventfd()

生成事件文件描述符

内核内部计数

poll() / epoll_wait() / select()

阻塞等待 fd 事件

可以被 eventfd 事件唤醒;也可以设置超时时间

优点:

  • 不需要 pthread mutex、不需要 cond;

  • 可以同时监听多个 fd(网络 fd + eventfd 唤醒 fd); 缺点:Linux 平台特有,不可移植。


四、容易混淆概念澄清

  1. pthread_cond_wait:无限等;pthread_cond_timedwait:带超时时间等待。两个都必须绑定 mutex

  2. sleep/nanosleep:时间睡眠,外部线程无法主动唤醒。

  3. eventfd+poll:IO 多路复用做唤醒,不用锁,Linux 特有。

选型速记

  1. 多线程共享队列( LAC 线程池场景)

用:pthread_cond_wait + mutex + while 判断条件。

  1. 需要等待,同时设置超时时间(条件变量)

用:pthread_cond_timedwait。注意参数是绝对时间,不是 “等待多少毫秒”。

  1. 只想让线程睡一会,不需要别人中途叫醒

用:nanosleep

  1. 需要外部线程主动唤醒,但是没有共享业务状态,不想用锁

Linux 下优先:eventfd + poll / epoll_wait


踩坑记录

pthread_cond_timedwait第二个时间参数是绝对时间,不是 “等待多久”。 举例子:想等待 500ms,不能直接填 500ms;要拿系统当前时间,加上 500ms,得到未来的时刻,传入进去。

简单对比

  • cond_wait:睡,等别人 signal 叫醒,必须带锁,无限等

  • cond_timedwait:睡,等叫醒或者时间到,必须带锁,有超时

  • nanosleep:单纯睡觉,别人叫不醒,只能等时间到


评论