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

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

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

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 关闭前让所有的协程都安全的退出的问题

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/langs/995614.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-21
下一篇 2022-05-21

发表评论

登录后才能评论

评论列表(0条)

保存