栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Go语言

golang模版-多协程的安全退出(避免goroutine泄漏)模版

Go语言 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

golang模版-多协程的安全退出(避免goroutine泄漏)模版

文章目录
  • 前置知识
  • 多协程安全退出粗糙版
  • 多协程安全退出完美版

golang 中很容易开启多个协程,那开启的这么多协程如何保证在 main 函数结束前这些协程都是安全退出呢(信道都安全关闭),这里我们使用到了 select,close 关闭信道函数以及 sync.WaitGroup 函数

前置知识

当信道被 close 掉之后,如果信道中有缓存,那么被关闭后是不能写的但是依然可以读取缓存数据,缓存被读完后读到的就是 0;如果信道中没有缓存,那么信道被关闭后直接读到的就是 0

多协程安全退出粗糙版
func worker(channel chan bool) {
    for {
        select {
        default:
            fmt.Println("hello world!")
        case <-channel:
			return
        }
    }
}

func main() {
    channel := make(chan bool)

    for i := 0; i < 10; i++ {
        go worker(channel)
    }

    time.Sleep(time.Second)
    close(channel)
}

为什么说这个是粗糙版呢?因为当 main 中的 close 函数执行关闭信道后,在极短时间内,可能会有一部分协程完成了

case <-channel:
	return

但是有可能并不是所有的协程都执行完 return 结束协程,可能还存在一些协程没有被彻底执行结束然后 main 函数就直接关闭了

多协程安全退出完美版
func worker(wg *sync.WaitGroup, channel chan bool) {
    defer wg.Done()

    for {
        select {
        default:
            fmt.Println("hello world!")
        case <- channel:
            return
        }
    }
}

func main() {
    channel := make(chan bool)

    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go worker(&wg, channel)
    }

    time.Sleep(time.Second)
    close(channel)
    wg.Wait()
}

当我们使用了 sync.WaitGroup 函数就可以保证当所有协程都完成了 wg.Done 即所有协程都被关闭后 wg.Wait 才会被放行
也就是说当信道被 close 后,会被卡在 wg.Wait,wg.Wait 函数会等到所有协程的 wg.Done 都被执行后(所有协程都被关闭后)才会放行 wg.Wait,这样也就完美解决了使用 select 和 close 当主协程 main 关闭前让所有的协程都安全的退出的问题

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/908423.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号