V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
LeeReamond
V2EX  ›  问与答

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

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

    所谓阻塞应该只是把自己线程的 context 挂起,又不会写个死循环傻等。。
    然后等内核的中断消息来触发线程复原。消息可以是时间或者 socket 收发事件。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2666 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:38 · PVG 19:38 · LAX 03:38 · JFK 06:38
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.