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

2019-10-15 11:55:07 +08:00
 lasuar
是的,我的意思有点类似 kill 它,而不是退出它。
我正在为实现这样一个功能苦恼,标准库中的 context, sync.WaitGroup 都只是辅助开发者来关闭或等待一个 goroutine 关闭,而我想要实现一个:func executeFunc(myFunc, timeout)的方式,当 timeout 到达时,直接 kill 这个 goroutine,而不需要传任何与任务函数无关的参数来侵入 goroutine。
在 Stack Overflow 上的答案是:没有这种方法,除非 Os.Exit to quit whole program.
大家来发表一下意见啊~~~
5354 次点击
所在节点    Go 编程语言
21 条回复
xeaglex
2019-10-15 12:15:24 +08:00
Select 可以用来实现超时
reus
2019-10-15 12:16:58 +08:00
没有这种东西,你这种设计才是粗暴的侵入吧

你可以用多个程序,然后用 exec.Cmd.Process.Kill
rrfeng
2019-10-15 12:20:03 +08:00
既然都设置 timeout 了那就用 context.Cancel() 呗。也加不了几行。
index90
2019-10-15 12:30:25 +08:00
标准的方式用 ctx 控制超时啊
yeya24
2019-10-15 12:31:56 +08:00
协程本身就不支持这样的,只能协程自己退出。你想结束它唯一办法就是 kill
lasuar
2019-10-15 12:32:17 +08:00
@reus 谢谢你提出的方法,不过这不是一种轻的实现方式没有满足我的想法。
不过请问下我的方式侵入什么了?怎么个侵入法?
lasuar
2019-10-15 12:32:58 +08:00
@xeaglex
@rrfeng
谢谢回复,不过你们没有理解我的意思
lasuar
2019-10-15 12:38:02 +08:00
@yeya24 但是 golang 不支持 kill 哇,或者说我不知道为什么 go 官方不提供 kill 方法。
reus
2019-10-15 12:39:19 +08:00
@lasuar 侵入了 goroutine 的执行

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

因为官方认为 goroutine 不应该有 id,那自然就不会有从外部控制的方法
lasuar
2019-10-15 12:50:32 +08:00
@reus 3q,我先看看
reus
2019-10-15 12:51:44 +08:00
@lasuar goroutine 不是协程,开发者也没法控制调度。

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

那么就只剩下 kill -9 的问题了:
线程 /进程是有独立的资源的,强制终结之后操作系统会回收处理。不会影响其他程序运行。
但是 goroutines 里有大量的共享资源,变量、内存、引用地址等等,根本无法辨别,所以就无法处理了。所以没有 kill -9
Leigg
2019-10-15 19:45:12 +08:00
@rrfeng 第一段话可以理解。 但是线程也可以使用全局变量,也可以做一些锁行为,这时候 kill 也会有问题,kill 与否由开发者决定。goroutine 拥有的资源线程一样有啊,你没有说到点子上。

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

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

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

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

© 2021 V2EX