V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
freemoon

如何非侵入式的停止一个 goroutine

  •  
  •   freemoon · Oct 15, 2019 · 5873 views
    This topic created in 2387 days ago, the information mentioned may be changed or developed.
    是的,我的意思有点类似 kill 它,而不是退出它。
    我正在为实现这样一个功能苦恼,标准库中的 context, sync.WaitGroup 都只是辅助开发者来关闭或等待一个 goroutine 关闭,而我想要实现一个:func executeFunc(myFunc, timeout)的方式,当 timeout 到达时,直接 kill 这个 goroutine,而不需要传任何与任务函数无关的参数来侵入 goroutine。
    在 Stack Overflow 上的答案是:没有这种方法,除非 Os.Exit to quit whole program.
    大家来发表一下意见啊~~~
    Supplement 1  ·  Oct 15, 2019
    更简单的阐述我的想法:
    线程记得吧,线程就有 kill/terminate 的方法来强行终止并回收资源。
    Supplement 2  ·  Oct 15, 2019
    此帖讨论结束
    21 replies    2019-10-15 20:39:36 +08:00
    xeaglex
        1
    xeaglex  
       Oct 15, 2019 via Android
    Select 可以用来实现超时
    reus
        2
    reus  
       Oct 15, 2019
    没有这种东西,你这种设计才是粗暴的侵入吧

    你可以用多个程序,然后用 exec.Cmd.Process.Kill
    rrfeng
        3
    rrfeng  
       Oct 15, 2019
    既然都设置 timeout 了那就用 context.Cancel() 呗。也加不了几行。
    index90
        4
    index90  
       Oct 15, 2019
    标准的方式用 ctx 控制超时啊
    yeya24
        5
    yeya24  
       Oct 15, 2019 via iPhone
    协程本身就不支持这样的,只能协程自己退出。你想结束它唯一办法就是 kill
    freemoon
        6
    freemoon  
    OP
       Oct 15, 2019
    @reus 谢谢你提出的方法,不过这不是一种轻的实现方式没有满足我的想法。
    不过请问下我的方式侵入什么了?怎么个侵入法?
    freemoon
        7
    freemoon  
    OP
       Oct 15, 2019
    @xeaglex
    @rrfeng
    谢谢回复,不过你们没有理解我的意思
    freemoon
        8
    freemoon  
    OP
       Oct 15, 2019
    @yeya24 但是 golang 不支持 kill 哇,或者说我不知道为什么 go 官方不提供 kill 方法。
    reus
        9
    reus  
       Oct 15, 2019
    @lasuar 侵入了 goroutine 的执行

    从外部是没法控制的,你可以想下怎样从内部控制,让函数里面不得不调用一些检查
    index90
        10
    index90  
       Oct 15, 2019
    goroutine 不是线程啊,而 go 又没有 vm 给你做协程的控制,协程就是有用户(开发者)自己用代码控制的啊。
    hst001
        11
    hst001  
       Oct 15, 2019
    你这个想法太暴力了,最好是协程能自己控制,超时到的时候释放各种资源然后退出协程
    freemoon
        12
    freemoon  
    OP
       Oct 15, 2019
    @index90 老哥点破我了,确实协程的概念是开发者调度的。好吧,也许是 golang 的 go func()这种极简的设计方式让我把对线程的思考方式代入协程里面了。
    reus
        13
    reus  
       Oct 15, 2019   ❤️ 1
    @lasuar https://tip.golang.org/doc/faq#no_goroutine_id

    因为官方认为 goroutine 不应该有 id,那自然就不会有从外部控制的方法
    freemoon
        14
    freemoon  
    OP
       Oct 15, 2019
    @reus 3q,我先看看
    reus
        15
    reus  
       Oct 15, 2019
    @lasuar goroutine 不是协程,开发者也没法控制调度。

    就算是操作系统线程,kill 系统调用也是发一个信号过去,退出不退出,线程本身也有一定选择权的,没有这么粗暴的
    t123yh
        16
    t123yh  
       Oct 15, 2019 via Android
    一个线程并不是随时都可以安全退出的,在某些状态下,一个线程并不能安全地退出,如果这时它被强行结束,可能会破坏程序状态。所以需要你在线程中的“安全地带”处检测是否要退出线程并主动退出,而不能直接从外部 kill 掉它。
    freemoon
        17
    freemoon  
    OP
       Oct 15, 2019
    @t123yh 了解,你说的是线程内使用了锁或者打开的文件资源这些情况吧。因为 kill 是 OS 提供的,调用是开发者执行的,所以开发者在 kill 的时候必须考虑到这些情况。这个就不在帖子讨论的主题范围了
    xeaglex
        18
    xeaglex  
       Oct 15, 2019 via Android   ❤️ 1
    。。。楼主问个问题还这么有性格
    rrfeng
        19
    rrfeng  
       Oct 15, 2019   ❤️ 2
    线程 /进程
    外部发送 kill 信号给它,它会在内部检测到,然后进行合适的处理,只是被封装好了你看不到这个而已 ---> 这个跟 context 解决 goroutine 是完全一致的。

    那么就只剩下 kill -9 的问题了:
    线程 /进程是有独立的资源的,强制终结之后操作系统会回收处理。不会影响其他程序运行。
    但是 goroutines 里有大量的共享资源,变量、内存、引用地址等等,根本无法辨别,所以就无法处理了。所以没有 kill -9
    Leigg
        20
    Leigg  
       Oct 15, 2019 via Android
    @rrfeng 第一段话可以理解。 但是线程也可以使用全局变量,也可以做一些锁行为,这时候 kill 也会有问题,kill 与否由开发者决定。goroutine 拥有的资源线程一样有啊,你没有说到点子上。
    useben
        21
    useben  
       Oct 15, 2019
    协程不是内核态的,不像进程和线程,分配了 pid,而且是应用层分配资源和调度的,所以没办法 kill
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   4417 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 56ms · UTC 04:11 · PVG 12:11 · LAX 21:11 · JFK 00:11
    ♥ Do have faith in what you're doing.