如何结束子 goroutinue 求助

j00279583 · 2017-09-16 13:05:52 · 1337 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2017-09-16 13:05:52 的主题,其中的信息可能已经有所发展或是发生改变。

最近遇到一个难题,求助一下各位大神。 如下面部分代码所示。 computedata 内部 调用的dosomething函数是一个很耗时的函数,通过复杂的计算返回一个结果,用于其他函数计算。但是dosomething 函数在一秒之内,仍然没有返回结果。那么就直接超时,timeout掉。 但是目前遇到的困难是 即使我们这个computedata函数杀死,dosomething函数让着后台运行,该函数会修改一些全局函数,下次调用是,会影响下次的计算结果,因此必须彻底杀死,如何才能杀死它呢?求助高手?

func main() {
    computedata()

    for{

    }
}

func computedata()  {

    var c = make(chan int,1)
    time := time.Now().Add(time.Second*1)
    ctx, cancel := context.WithDeadline(context.Background(),time)
    defer cancel()

    go dosomething(c)

    select {
    case <-ctx.Done():
        fmt.Println("time out.")
        return

    case data :=<-c:
        fmt.Println(data)
        return
    }

}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1337 次点击  
加入收藏 微博
8 回复  |  直到 2017-09-21 15:32:05
lwldcr
lwldcr · #1 · 7年之前

go dosomething() 怎么没把ctx带过去。。ctx不就是做这个事的么 然后select{} 在dosomething里做,就能在timeout到了之后return,结束这个goroutine了

j00279583
j00279583 · #2 · 7年之前

你的意思是这个吗? 但是realdosometing 一直占用cpu啊。不能走到 done的那个分支啊? 求指教。

func dosomething(ctx){
    select {
    case <-ctx.Done():
        fmt.Println("time out.")
    default: // realdosomething
    }
}
j00279583
j00279583 · #3 · 7年之前
lwldcrlwldcr #1 回复

go dosomething() 怎么没把ctx带过去。。ctx不就是做这个事的么 然后select{} 在dosomething里做,就能在timeout到了之后return,结束这个goroutine了

你的意思是这个吗? 但是realdosometing 一直占用cpu啊。不能走到 done的那个分支啊? 求指教。

func dosomething(ctx){
    select {
    case <-ctx.Done():
        fmt.Println("time out.")
    default: // realdosomething
    }
}
alex_023
alex_023 · #4 · 7年之前

要打断 select 操作,case 语句中,绝不允许出现 default,即使你用了 ctx.Done也是如此。只能适应这个结构,没的选择。

lwldcr
lwldcr · #5 · 7年之前

default分支的计算很耗时的话,它就一直占着cpu,即便ctx.Done()有消息也不能得到执行 可以试着分割realdosomething的操作 同时在realdosomething之前保留状态,如果最后是ctx.Done()执行了,就恢复现场

lwldcr
lwldcr · #6 · 7年之前
j00279583j00279583 #2 回复

你的意思是这个吗? 但是realdosometing 一直占用cpu啊。不能走到 done的那个分支啊? 求指教。 ```go func dosomething(ctx){ select { case <-ctx.Done(): fmt.Println("time out.") default: // realdosomething } } ```

你这里只有select,那select里的分支最多只有一次机会得到执行,选中哪个执行完毕就退出了 外面加个循环,ctx.Done()分支里用return

for {
select {
   }
}
j00279583
j00279583 · #7 · 7年之前
lwldcrlwldcr #6 回复

#2楼 @j00279583 你这里只有select,那select里的分支最多只有一次机会得到执行,选中哪个执行完毕就退出了 外面加个循环,ctx.Done()分支里用return ``` for { select { } } ```

外面是应该加for , 但是这个不是关键,那个realdosometing 一直占用着cpu。导致其他分支无法进入。

sevenhe
sevenhe · #8 · 7年之前

我觉得调度是go去处理的,业务开发不必管这个goroutine是否一直占用着cpu,没使用多核的情况下,看着可能是这个readsomething占用cpu,但是很有可能其他goroutine也得到了cpu的时间片。 回到这个问题,不知道我理解的对不对,也不知道你这个修改全局函数是啥意思,我理解就是相当修改全局的变量,既然readsomething修改了全局函数,那么不如把全局函数赋值给一个变量,然后对变量进行修改,timeout后,这个变量在栈中也被释放了,不会影响全局;假如最后返回结果,可以在返回结果之前,将修改的值重新赋给全局值,也达到了修改的目的。

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传