「让我们一起Golang」让协程自己kill自己

简介: 「让我们一起Golang」让协程自己kill自己

「让我们一起Golang」让协程自己kill自己

我们这篇博文讨论Go的协程杀掉自己协程的有关内容。这里我们就需要用到runtime.Goexit().

先上代码介绍runtime.Goexit()及其使用方法

package main

import (
    "fmt"
    "runtime"
    "time"
)

func task051()  {
    defer fmt.Println("拿来吧你")

    fmt.Println("曲项向天歌")
    fmt.Println("白毛浮绿水")
    //杀死当前所在协程
    // Goexit terminates the goroutine that calls it. No other goroutine is affected.
    // Goexit runs all deferred calls before terminating the goroutine. Because Goexit
    // is not a panic, any recover calls in those deferred functions will return nil.
    //
    // Calling Goexit from the main goroutine terminates that goroutine
    // without func main returning. Since func main has not returned,
    // the program continues execution of other goroutines.
    // If all other goroutines exit, the program crashes.
    runtime.Goexit()

    fmt.Println("红掌拨清波")
}

func main() {
    go func() {
        fmt.Println("鹅鹅鹅")
        task051()
        fmt.Println("——骆宾王")
    }()
    // Sleep pauses the current goroutine for at least the duration d.
    // A negative or zero duration causes Sleep to return immediately.
    time.Sleep(time.Second)
}

如果Goexit 杀掉它的 goroutine,其他 goroutine 也不会受到影响。 Goexit 在终止 goroutine 之前会调用所有延迟函数, 因为 Goexit 不是一个panic,而这些延迟函数中的任何调用恢复都将返回 nil。
从主协程调用 Goexit 会终止主协程,而不会返回主函数func main。 由于 主函数func main 没有返回,程序会继续执行其他 goroutine。 如果所有其他 goroutine 都终止,那么程序就会崩溃。

在这段代码里面,主函数中是先开辟一条协程,先输出《咏鹅》的第一句诗句,然后进入任务函数。该任务函数是执行在子协程中。

这段代码的运行结果是

鹅鹅鹅
曲项向天歌
白毛浮绿水
拿来吧你

这里“红掌拨清波”并没有输出,因为它是在runtime.Goexit()之后的语句,而此时协程已经被自己杀死了。

但是延迟函数被执行了,Goexit 在终止 goroutine 之前会调用所有延迟函数, 因为 Goexit 不是一个panic,而这些延迟函数中的任何调用恢复都将返回 nil。所以“拿来吧你”不会输出。

但是作者名”——骆宾王“为什么也没输出呢?思考一下吧。

因为函数task051()里面将当前协程kill掉了。而作者名”——骆宾王“因为协程已经被杀死而执行不到。

前面杀死的是子协程。

我们之前说主协程不能死,那么我们现在杀死主协程看看会怎么样吧!

主协程被杀死之后,所有子协程就会乱了套,不眠不休。

我们先来看看主协程正常结束的样子吧...

func main() {
    go task061()
    //主协程睡5秒
    time.Sleep(5 * time.Second)

    //runtime.Goexit()
}
func task061(){
    for{
        fmt.Println("任务进行中...")
        time.Sleep(time.Second)
    }
}

运行结果是:

任务进行中...
任务进行中...
任务进行中...
任务进行中...
任务进行中...

主协程睡觉睡了5秒,子协程没睡一秒就说一句“任务进行中...”,所以当主协程结束时,主协程说五句“任务进行中...”。

现在我们杀死主协程看看会出现什么吧!

将上面代码块的runtime.Goexit()激活,让他能够运行。

看看运行结果吧。

任务进行中...
任务进行中...
...(中间省略若干)
任务进行中...

博主等了半分钟,子协程一直在那大喊“任务进行中...”,像极了晚上父母不在家,大喊大叫的熊孩子。

目录
相关文章
|
3月前
|
安全 Go
Golang语言goroutine协程并发安全及锁机制
这篇文章是关于Go语言中多协程操作同一数据问题、互斥锁Mutex和读写互斥锁RWMutex的详细介绍及使用案例,涵盖了如何使用这些同步原语来解决并发访问共享资源时的数据安全问题。
101 4
|
4月前
|
Go 调度 开发者
[go 面试] 深入理解进程、线程和协程的概念及区别
[go 面试] 深入理解进程、线程和协程的概念及区别
|
1月前
|
存储 安全 测试技术
GoLang协程Goroutiney原理与GMP模型详解
本文详细介绍了Go语言中的Goroutine及其背后的GMP模型。Goroutine是Go语言中的一种轻量级线程,由Go运行时管理,支持高效的并发编程。文章讲解了Goroutine的创建、调度、上下文切换和栈管理等核心机制,并通过示例代码展示了如何使用Goroutine。GMP模型(Goroutine、Processor、Machine)是Go运行时调度Goroutine的基础,通过合理的调度策略,实现了高并发和高性能的程序执行。
122 29
|
5月前
|
Java Go 调度
GO 协程
GO 协程
45 0
|
1月前
|
Go 计算机视觉
在Golang高并发环境中如何进行协程同步?
在此示例中,使用互斥锁来保护对共享计数器变量 c 的访问,确保并发的 HTTP 请求不会产生数据竞争。
46 3
|
1月前
|
负载均衡 算法 Go
GoLang协程Goroutiney原理与GMP模型详解
【11月更文挑战第4天】Goroutine 是 Go 语言中的轻量级线程,由 Go 运行时管理,创建和销毁开销小,适合高并发场景。其调度采用非抢占式和协作式多任务处理结合的方式。GMP 模型包括 G(Goroutine)、M(系统线程)和 P(逻辑处理器),通过工作窃取算法实现负载均衡,确保高效利用系统资源。
|
2月前
|
安全 Go 调度
探索Go语言的并发模式:协程与通道的协同作用
Go语言以其并发能力闻名于世,而协程(goroutine)和通道(channel)是实现并发的两大利器。本文将深入了解Go语言中协程的轻量级特性,探讨如何利用通道进行协程间的安全通信,并通过实际案例演示如何将这两者结合起来,构建高效且可靠的并发系统。
|
3月前
|
Go 调度
Golang语言goroutine协程篇
这篇文章是关于Go语言goroutine协程的详细教程,涵盖了并发编程的常见术语、goroutine的创建和调度、使用sync.WaitGroup控制协程退出以及如何通过GOMAXPROCS设置程序并发时占用的CPU逻辑核心数。
74 4
Golang语言goroutine协程篇
|
4月前
|
监控 Devops 测试技术
|
4月前
|
NoSQL Unix 编译器
Golang协程goroutine的调度与状态变迁分析
文章深入分析了Golang中goroutine的调度和状态变迁,包括Grunnable、Gwaiting、Grunning和Gsyscall等状态,以及它们之间的转换条件和原理,帮助理解Go调度器的内部机制。
55 0