异步编程中的睡眠是如何实现的?

2021-04-21 07:14:05 +08:00
 LeeReamond
想到个问题,异步一般是用来处理网络 io,文件 io 或者睡眠这三类需求,前两类需求比较好理解,将文件描述符交给 epoll 监听,无反馈时阻塞整个程序,有反馈时就执行事件循环逻辑,思路很清晰。但是睡眠这个是怎么实现的呢,睡眠又没有个什么描述符指向
1156 次点击
所在节点    问与答
12 条回复
araaaa
2021-04-21 07:49:50 +08:00
一般会用时间轮
Mohanson
2021-04-21 07:56:23 +08:00
RTFD
pabupa
2021-04-21 08:23:00 +08:00
主循环除了处理 io,还有一个 timeout 的堆,和一个 callback 的链表。
sleep 就是加一个 timeout 。
codehz
2021-04-21 08:24:55 +08:00
可以有 timerfd 来着的,不过似乎大家都是自己用 epoll 的超时机制实现,毕竟文件句柄多了对性能也有影响的(
soulzz
2021-04-21 08:31:38 +08:00
参考 netty
Hash Wheel Timer
https://zhuanlan.zhihu.com/p/65835110
LeeReamond
2021-04-21 09:41:38 +08:00
@pabupa 问题是如果 timeout 和 epoll 是两个东西,那一个循环怎么同时监听这两个呢。。比如它清空了 epoll 任务,那就阻塞在 epoll 上了,这时候如果 timeout 发生了,但线程又不能唤醒自己
sujin190
2021-04-21 09:49:43 +08:00
@LeeReamond #6 epoll 等待的时候可以设置一个等待超时时间,然后把下一个 timer 超时的时间设置为 epoll 等待超时的时间就行了,epoll 超时返回不会给出任何 fd,所以啥也不干去检查是否有 timer 超时就好了
LeeReamond
2021-04-21 09:51:34 +08:00
@sujin190 感谢回复,是一种可行解决方案,大概就是楼上说的 epoll 机制的那种解法吧,根据楼上回复似乎还有其他方案。不过这样又叫人好奇起来 epoll 的超时是怎么实现的,神奇的计算机系统啊
pabupa
2021-04-21 11:33:56 +08:00
@LeeReamond #6 epoll 也可以立即返回啊。
当 timeout 和 callback 都为空时,再阻塞调用。有一个不为空,就立即返回。
pabupa
2021-04-21 11:39:04 +08:00
3dwelcome
2021-04-21 12:14:16 +08:00
Windows 才是异步编程的鼻祖,当年 JS 陷入回调地狱的时候,Windows 消息机制把所有函数都变成消息收发事件,把代码逻辑安排井井有条,一个 case 对应一个任务。
epoll 超时应该也是抄这种模式,调用后就阻塞,只有被外界消息触发后,才会返回一个结果。
3dwelcome
2021-04-21 12:22:36 +08:00
@LeeReamond "比如它清空了 epoll 任务,那就阻塞在 epoll 上了,这时候如果 timeout 发生了,但线程又不能唤醒自己"

所谓阻塞应该只是把自己线程的 context 挂起,又不会写个死循环傻等。。
然后等内核的中断消息来触发线程复原。消息可以是时间或者 socket 收发事件。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/772055

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX