2021-03-11:go中,协程内部再启用协程,它们是没关系,对吧?外部协程奔溃,内部协程还会执行

福大大 · · 393 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

2021-03-11:go中,协程内部再启用协程,它们是没关系,对吧?外部协程奔溃,内部协程还会执行吗?外部协程执行结束的时候,如何让内部协程也停止运行?golang原生提供的包里,让内部协程停止运行,如何实现?
福哥答案2021-03-11:
1.外部协程和内部协程没关系。
2.如果程序不奔溃,不会影响内部协程继续执行。如果没做特殊处理,整个程序会奔溃。
3.三种方式:共享变量作为标志位,通道,上下文context。这三种方式均是协作式中断,不是抢占式。对于程序员,是无法实现抢占式中断的。

如果能实现抢占式,请发代码,谢谢。

代码用golang编写,代码如下:

package main

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

func main() {
    input := 0
    for {
        fmt.Println("1.标志位方式")
        fmt.Println("2.通道方式")
        fmt.Println("3.上下文方式")
        fmt.Println("4.退出")
        fmt.Println("请输入数字:")
        fmt.Scanf("%d", &input)
        switch input {
        case 1:
            go outer1()
        case 2:
            go outer2()
        case 3:
            go outer3()
        default:
            return
        }
        time.Sleep(time.Second * 7)
    }
    fmt.Scanf("%d", &input)

}

//1.标志位
func outer1() {
    isInterrupt := false
    inner := func() {
        for {

            if isInterrupt {
                fmt.Println("inner1 退出")
                break
            } else {
                fmt.Println("inner1 执行中...")
                time.Sleep(time.Second * 1)
            }
        }
    }
    go inner()
    fmt.Println("outer1 等待中... 5s")
    time.Sleep(time.Second * 5)
    isInterrupt = true
    fmt.Println("outer1 退出")
}

//2.通道
func outer2() {
    c := make(chan struct{}, 1)
    inner2 := func() {
        for {
            select {
            case <-c:
                fmt.Println("inner2 退出...")
                return
            default:
                fmt.Println("inner2 执行中...")
                time.Sleep(time.Second * 1)
            }
        }
    }
    go inner2()
    fmt.Println("outer2 等待中... 5s")
    time.Sleep(time.Second * 5)
    c <- struct{}{}
    fmt.Println("outer2 退出")
}

//3.context
func outer3() {
    ctx, cancel := context.WithCancel(context.Background())
    inner3 := func() {
        for {
            select {
            case <-ctx.Done():
                fmt.Println("inner3 退出...")
                return
            default:
                fmt.Println("inner3 执行中...")
                time.Sleep(time.Second * 1)
            }
        }
    }
    go inner3()
    fmt.Println("outer3 等待中... 5s")
    time.Sleep(time.Second * 5)
    //操作
    cancel()
    fmt.Println("outer3 退出")
}

执行结果如下:
在这里插入图片描述


知乎答案
评论


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

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

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