2021-03-11:go中,协程内部再启用协程,它们是没关系,对吧?外部协程奔溃,内部协程还会执行吗?外部协程执行结束的时候,如何让内部协程也停止运行?golang原生提供的包里,让内部协程停止运行,如何实现?

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 退出")
}

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


知乎答案
评论

posted @   福大大架构师每日一题  阅读(116)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
点击右上角即可分享
微信分享提示