V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
Askiz
V2EX  ›  编程

在函数中开启协程或进程递归调用自身会引起栈溢出吗?

  •  
  •   Askiz · 2022-07-14 22:19:30 +08:00 · 1345 次点击
    这是一个创建于 860 天前的主题,其中的信息可能已经有所发展或是发生改变。
    起因是在学 openresty 的时候官方 lua-nginx-module 里官方介绍 ngx.timer.at 的使用方法,介绍了一种定时器的写法


    这是用递归调用实现的定时器,查看源码 ngx.timer.at 是异步的,使用时是创建一个 coroutine 运行子函数。
    一般来说无限递归调用自身会导致栈溢出,但是这个例子我测试了并不会栈溢出。
    于是测试了 golang 的在函数中开启协程递归调用自身:


    测试 python3 在函数中开启线程递归调用自身:


    上面这两个也并不会产生栈溢出,请问这是为什么呢?
    7 条回复    2022-07-14 23:19:00 +08:00
    learningman
        1
    learningman  
       2022-07-14 22:23:07 +08:00 via Android
    尾递归转循环了吧
    Askiz
        2
    Askiz  
    OP
       2022-07-14 22:25:31 +08:00
    @learningman #1 python 和 go 并不支持对尾递归的优化
    misdake
        3
    misdake  
       2022-07-14 22:42:58 +08:00
    新线程和协程得到的是一个新的栈。不依赖创建时的栈。
    Askiz
        4
    Askiz  
    OP
       2022-07-14 22:54:15 +08:00
    @misdake #3 嗯嗯,如果栈是独立的,那创造无限个独立的栈会溢出吗?
    darklights
        5
    darklights  
       2022-07-14 23:04:30 +08:00
    05 秒:创建 coroutine#1 运行 handler#1 ,注册 handler#2 ,coroutine#1 结束
    10 秒:创建 coroutine#2 运行 handler#2 ,注册 handler#3 ,coroutine#2 结束
    ……

    并没有无限递归
    djoiwhud
        6
    djoiwhud  
       2022-07-14 23:08:56 +08:00 via Android
    go 的例子显然不是递归。
    你只是不停的创建 goroutine ,这个是生成了一个 goroutine 运行时环境,然后这个运行时环境很快就退出了回收了(调度线程回收了)。
    你要是不用 goroutine ,必然会溢出。
    Askiz
        7
    Askiz  
    OP
       2022-07-14 23:19:00 +08:00 via Android
    @darklights 嗯嗯 谢谢解答
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3345 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 11:41 · PVG 19:41 · LAX 03:41 · JFK 06:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.