首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >被超时取消的上下文,但计算没有中止吗?

被超时取消的上下文,但计算没有中止吗?
EN

Stack Overflow用户
提问于 2021-04-11 20:04:52
回答 2查看 1.6K关注 0票数 1

试图理解go上下文取消将如何中止后续代码的执行

实验细节:

  1. main func有一个在2sec中超时的上下文
  2. main func在一个单独的go-例程中调用另一个func sum -用于测试运行的1sec -1和测试运行的4sec -2。
  3. 3sec的主睡眠让旋转完成执行
代码语言:javascript
复制
package main

import (
    "context"
    "fmt"
    "log"
    "time"
)

func main() {

    c := context.Background()
    childCtx, cancel := context.WithTimeout(c, 2*time.Second)
    defer cancel()

    ch := make(chan int, 1)
    go sum(5, 6, ch)

    var msg string

    select {
    case <-childCtx.Done():
        msg = "return from ctx done channel"
    case res := <-ch:
        msg = fmt.Sprintf("return from go routine: %v", res)
    }

    log.Print(msg)

    time.Sleep(3 * time.Second) //sleeping here to test if go-routine is still running
}


func sum(x int, y int, c chan<- int) {
    time.Sleep(1 * time.Second) 
    //testcase-1: sleep - 1s
    //testcase-2: sleep - 4s

    result := x + y

    log.Printf("print from sum fn: %v", result)

    c <- result
}

对testcase的响应-1:睡眠和函数1秒:

代码语言:javascript
复制
2021/04/12 01:06:58 print from sum fn: 11
2021/04/12 01:06:58 return from go routine: 11

对testcase-2的响应:睡眠和函数4秒:

代码语言:javascript
复制
2021/04/12 01:08:25 return from ctx done channel
2021/04/12 01:08:27 print from sum fn: 11

在testcase-2中,当sum func休眠4秒时,上下文在2秒后已经被超时所取消,为什么它仍然在diff go例程中执行sum func并打印print from sum fn: 1

来自文档:取消此上下文将释放与其相关的资源。

我的假设是,所有的计算都会在2秒后立即中止,包括旋转的go例程。

让我知道如何正确地做这件事,谢谢

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-04-11 20:27:46

正如@AndySchweig所指出的,context发出取消事件的信号,但不强制取消。这取决于任何潜在的阻塞戈鲁丁,尽其最大的努力,试图取消/清理后,它检测到取消。

要更新sum函数以支持取消,您可以尝试:

代码语言:javascript
复制
// add context parameter as the first argument
// add a return error - to indicate any errors (i.e. function was interrupted due to cancelation)
func sum(ctx context.Context, x int, y int, c chan<- int) (err error) {

    wait := 1 * time.Second // testcase-1
    //wait := 4 * time.Second // testcase-2

    // any blocking called - even sleeps - should be interruptible
    select {
    case <-time.After(wait):
    case <-ctx.Done():
        err = ctx.Err()
        return
    }

    result := x + y

    log.Printf("print from sum fn: %v", result)

    select {
    case c <- result:
    case <-ctx.Done(): // check for ctx cancelation here - as no one may be listening on result channel
        err = ctx.Err()
    }
    return
}

https://play.golang.org/p/DuIACxPvHYJ

票数 4
EN

Stack Overflow用户

发布于 2021-04-11 20:34:05

上下文不会中止go例程。在您的例子中,如果上下文的时间超出,您就不会打印go例程的结果。go例程对上下文一无所知。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67049687

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档