goroutine 并發(fā)常見問題實(shí)踐

程序退出時(shí)運(yùn)行的 goroutine 會(huì)不會(huì)被終止

測(cè)試代碼:

import (
    "time"
    "fmt"
)

func main() {
    for i := 0; i < 10; i ++ {
        go func(j int) {
            fmt.Println(j)
        }(i)
    }
    time.Sleep(3*time.Microsecond)
    return
}

運(yùn)行結(jié)果:

?  test go run ./test_goroutine.go
0
1
2
3
4
5
6
7
8
9
?  test go run ./test_goroutine.go
5
4
6
?  test go run ./test_goroutine.go
?  test go run ./test_goroutine.go

結(jié)論:主程序結(jié)束時(shí)還在運(yùn)行中的 goroutine 也會(huì)終止。

怎樣讓主程序等待所有 goroutine 退出:

  • 使用管道 channel,適用于單個(gè) goroutine

    func main() {
        ch := make(chan int)
        go func(c chan int){
            time.Sleep(time.Second * 3)
            fmt.Println("goroutine 即將結(jié)束。")
            c <- 1
        }(ch)
    
        fmt.Println("主程序即將結(jié)束。")
    
        <- ch
    
        fmt.Println("主程序退出。")
    }
    

    運(yùn)行結(jié)果:

    主程序即將結(jié)束。
    goroutine 即將結(jié)束。
    主程序退出。
    
  • 使用 WaitGroup

    import (
        "fmt"
        "sync"
    )
    
    func main() {
        wg := sync.WaitGroup{}
    
        // wg.Add(10)
        for i := 0; i < 10; i++ {
            wg.Add(1)
            go func(j int, wg *sync.WaitGroup) {
                defer wg.Done()
                fmt.Printf("goroutine %d 即將退出。\n", j + 1)
            }(i, &wg) // 此處注意使用指針傳遞,否則 goroutine 中的 wg 為新的對(duì)象
        }
    
        fmt.Println("主程序即將退出。")
        wg.Wait()
        fmt.Println("主程序退出。")
    }
    

    運(yùn)行結(jié)果:

    主程序即將退出。
    goroutine 4 即將退出。
    goroutine 1 即將退出。
    goroutine 2 即將退出。
    goroutine 3 即將退出。
    goroutine 7 即將退出。
    goroutine 5 即將退出。
    goroutine 6 即將退出。
    goroutine 9 即將退出。
    goroutine 10 即將退出。
    goroutine 8 即將退出。
    主程序退出。
    
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容