golang fatal error: all goroutines are asleep - deadlock!

channel默認上是阻塞的,也就是說,若是Channel滿了,就阻塞寫,若是Channel空了,就阻塞讀。阻塞的含義就是一直等到輪到它爲止。單有時候咱們會收到 fatal error: all goroutines are asleep - deadlock!  異常,這是如何呢? 協程

代碼例子:blog

package main get

import "fmt" string

func main() {
    channel := make(chan string, 2) it

    fmt.Println("1")
    channel <- "h1"
    fmt.Println("2")
    channel <- "w2"
    fmt.Println("3")
    channel <- "c3"    // 執行到這一步,直接報 error
    fmt.Println("...")
    msg1 := <-channel
    fmt.Println(msg1)
}io

執行效果:import

image

參考:select

http://stackoverflow.com/questions/26927479/go-language-fatal-error-all-goroutines-are-asleep-deadlockchannel

 

fatal error: all goroutines are asleep - deadlock! 程序

出錯信息的意思是:
在main goroutine線,指望從管道中得到一個數據,而這個數據必須是其餘goroutine線放入管道的
可是其餘goroutine線都已經執行完了(all goroutines are asleep),那麼就永遠不會有數據放入管道。
因此,main goroutine線在等一個永遠不會來的數據,那整個程序就永遠等下去了。
這顯然是沒有結果的,因此這個程序就說「算了吧,不堅持了,我本身自殺掉,報一個錯給代碼做者,我被deadlock了」

 

這裏是系統自動在除了主協程以外的協程都關閉後,作的檢查,繼而報出的錯誤, 證實思路以下, 在100秒內, 咱們看不到異常, 100秒後,系統報錯。

package main

import (
    "fmt"
    "time"
)

func main() {
    channel := make(chan string, 2)

    go func() {
        fmt.Println("sleep 1")
        time.Sleep(100 * time.Second)
        fmt.Println("sleep 2")
    }()

    fmt.Println("1")
    channel <- "h1"
    fmt.Println("2")
    channel <- "w2"

    fmt.Println("3")
    channel <- "c3"

    fmt.Println("...")
    msg1 := <-channel
    fmt.Println(msg1)
}

100秒內執行效果截圖:

image

100秒後執行效果截圖:

image

 

若是避免上面異常拋出呢?這時候咱們能夠用 select來幫咱們處理。

package main

import "fmt"

func main() {
    channel := make(chan string, 2)

    fmt.Println("1")
    channel <- "h1"
    fmt.Println("2")
    channel <- "w2"

    fmt.Println("3")
    select {

    case channel <- "c3":
        fmt.Println("ok")
    default:
        fmt.Println("channel is full !")
    }

    fmt.Println("...")
    msg1 := <-channel
    fmt.Println(msg1)
}

執行效果:

image

這時候,咱們把第三個要寫入的 chan 拋棄了。

 

上面的例子中是寫的例子, 讀的例子也同樣,下面的異常是  ws := <-channel 這一行拋出的。

channel := make(chan string, 2)

fmt.Println("begin")
ws := <-channel
fmt.Println(ws)

image

相關文章
相關標籤/搜索