關於Golang使用channel的死鎖問題

2021-10-01 15:39:39 字數 3549 閱讀 7387

小白一枚,最近在入門學習golang,在學到channel時,發現總會遇到死鎖的問題:

fatal error: all goroutines are asleep - deadlock!

所以,當我們寫的程式生產和消費的數量不對等時,便會發生阻塞造成死鎖

生產者阻塞:

生產4條訊息,只消費3條

package main

import (

"fmt"

"sync"

)var wg sync.waitgroup

func producer(ch chan<- int)

}func consumer(ch <-chan int)

}func main()

goroot=/usr/local/go #gosetup

gopath=/users/why/desktop/go #gosetup

/usr/local/go/bin/go build -o /private/var/folders/_s/jfrm6_712w58sytpc753pmr40000gn/t/___go_build_why_go /users/why/desktop/go/why.go #gosetup

/private/var/folders/_s/jfrm6_712w58sytpc753pmr40000gn/t/___go_build_why_go #gosetup

result: 1

result: 2

result: 3

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:

sync.runtime_semacquire(0x1195ae8)

/usr/local/go/src/runtime/sema.go:56 +0x42

sync.(*waitgroup).wait(0x1195ae0)

/usr/local/go/src/sync/waitgroup.go:130 +0x64

main.main()

/users/why/desktop/go/why.go:30 +0xb1

goroutine 18 [chan send]:

main.producer(0xc000070060)

/users/why/desktop/go/why.go:12 +0x7c

created by main.main

/users/why/desktop/go/why.go:27 +0x7f

process finished with exit code 2

可以發現錯誤出現在chan send

消費者阻塞:

消費4條訊息,只生產3條

package main

import (

"fmt"

"sync"

)var wg sync.waitgroup

func producer(ch chan<- int)

}func consumer(ch <-chan int)

}func main()

goroot=/usr/local/go #gosetup

gopath=/users/why/desktop/go #gosetup

/usr/local/go/bin/go build -o /private/var/folders/_s/jfrm6_712w58sytpc753pmr40000gn/t/___go_build_why_go /users/why/desktop/go/why.go #gosetup

/private/var/folders/_s/jfrm6_712w58sytpc753pmr40000gn/t/___go_build_why_go #gosetup

result: 1

result: 2

result: 3

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:

sync.runtime_semacquire(0x1195ae8)

/usr/local/go/src/runtime/sema.go:56 +0x42

sync.(*waitgroup).wait(0x1195ae0)

/usr/local/go/src/sync/waitgroup.go:130 +0x64

main.main()

/users/why/desktop/go/why.go:30 +0xb1

goroutine 7 [chan receive]:

main.consumer(0xc000070060)

/users/why/desktop/go/why.go:19 +0x9b

created by main.main

/users/why/desktop/go/why.go:28 +0xa1

process finished with exit code 2

可以發現錯誤出現在chan receive

實際應用場景,我們並不能預先知道生產者和消費者的準確數量,該如何保證不發生阻塞造成死鎖呢?

golang中提供了乙個函式:close(ch),該函式是用來關閉通道的,我們在傳送完需要傳送的資料後,就用close將通道關閉,訊息接收端接收可以借用 for range 語句進行多個元素的接收操作

舉個例子幫助理解:北京的早高峰是非常嚇人的,尤其是著名的天通苑,每天地鐵都會進行限流,工作人員限流(用close關閉通道)後,人就不再進入地鐵站(傳送的協程停止傳送訊息),而進入地鐵站的人都按照進站(訊息產生)的順序依次進行安檢(通過for range依次獲取訊息),進入地鐵站乘坐地鐵(消費者處理)。

所以最終**如下:

package main

import (

"fmt"

"sync"

)var wg sync.waitgroup

func producer(ch chan<- int)

close(ch)

}func consumer(ch <-chan int)

}func main()

gopath=/users/why/desktop/go #gosetup

/usr/local/go/bin/go build -o /private/var/folders/_s/jfrm6_712w58sytpc753pmr40000gn/t/___go_build_why_go /users/why/desktop/go/why.go #gosetup

/private/var/folders/_s/jfrm6_712w58sytpc753pmr40000gn/t/___go_build_why_go #gosetup12

345process finished with exit code 0

關於golang面向介面

傳統語言的繼承多型由go語言的介面完成 所以go語言的介面比較靈活 go語言介面由使用者定義 傳統語言由實現者定義 先來乙個簡單的介面示例 package mock 介面方法專用包 type retriever struct func r retriever get url string strin...

Golang 在Golang中使用json

由於要開發乙個小型的web應用,而web應用大部分都會使用json作為資料傳輸的格式,所以有了這篇文章。包引用import 用於存放資料的結構體type mydata struct這裡需要注意的就是後面單引號中的內容。json item 這個的作用,就是name欄位在從結構體例項編碼到json資料格...

Golang 關於通道 Chan 詳解

首先我們來看執行緒,在golang裡面也叫goroutine 下面我們先來看乙個例子吧 import fmt funcmain 在golang裡面,使用go這個關鍵字,後面再跟上乙個函式就可以建立乙個執行緒。後面的這個函式可以是已經寫好的函式,也可以是乙個匿名函式 funcmain i fmt.pr...