簡體   English   中英

為什么這種goroutine泄漏?

[英]Why this goroutine leaks?

我正在閱讀“ Go中的並發性”,並且發現了goroutine泄漏的以下示例:

func main() {

    var wg sync.WaitGroup

    doWork := func(strings <-chan string) <-chan interface{} {
        completed := make(chan interface{})
        go func() {
            defer fmt.Println("doWork exited.")
            defer close(completed)
            defer wg.Done()
            fmt.Println("a")
            for s := range strings {
                fmt.Println(s)
            }
            fmt.Println("b")
        }()
        return completed
    }

    wg.Add(1)
    doWork(nil)
    fmt.Println("Waiting")
    wg.Wait()

    fmt.Println("Done.")
}

strings通道將永遠不會寫入任何字符串,並且包含doWork的goroutine將在進程的整個生命周期內保留在內存中。

我不明白-為什么?

我如何理解此代碼:

  • 由於stringsnil range -loop只是跳過了。 作為任何超過nil范圍:

     slice := []int{10, 20, 30, 40, 50} slice = nil for i := range slice { fmt.Println(i) } fmt.Println("Done") 
  • fmt.Println("doWork exited.")將被執行

  • close(completed)將被執行

但我看到它像那樣工作。 為什么呢

由於字符串為零,因此僅跳過了范圍循環。

這個假設是不正確的。 在Go中,從nil通道讀取將始終受阻。 這是在語言規范中定義的(感謝@peterSO挖掘出鏈接):

從零信道接收將永遠阻止。

Go Design Patterns博客上還有一篇文章 ,進一步闡述了這種行為,並重點介紹了一些有用的情況。

無論如何,可以通過一個最小的示例( Playground )輕松地重現此行為:

func main() {
    var s chan string
    <- s
}

該程序將永遠不會完成(在操場上, all goroutines are asleep - deadlock將進入all goroutines are asleep - deadlock ,這將使其崩潰all goroutines are asleep - deadlock )。

因為從nil通道(在您的示例中為strings )讀取將被阻塞(永遠,因為無法將任何內容寫入nil通道),所以doWork goroutine將永遠不會完成,因此會泄漏。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM