golang channel幾點總結
阿新 • • 發佈:2018-11-24
golang提倡使用通訊來共享資料,而不是通過共享資料來通訊。channel就是golang這種方式的體現。
Channel
在golang中有兩種channel:帶快取的和不帶快取。
- 帶快取的channel,也就是可以非同步收發的。
- 不帶快取的channel,也就是同步收發的。
傳送:
• 向 nil channel 傳送資料,阻塞。
• 向 closed channel 傳送資料,出錯。
• 同步傳送: 如有接收者,交換資料。否則排隊、阻塞。
• 非同步傳送: 如有空槽,拷⻉貝資料到緩衝區。否則排隊、阻塞。
接收:
• 從 nil channel 接收資料,阻塞。
• 從 closed channel 接收資料,返回已有資料或零值。
• 同步接收: 如有傳送者,交換資料。否則排隊、阻塞。
• 非同步接收: 如有緩衝項,拷⻉貝資料。否則排隊、阻塞。
底層實現
使用channel時,多個goroutine併發傳送和接收,卻無需加鎖,為什麼呢?
其實,是由底channel層實現做支撐的。
channel的具體定義參見/usr/local/go/src/runtime/chan.go
type hchan struct {
qcount uint // total data in the queue
dataqsiz uint // size of the circular queue
buf unsafe.Pointer // points to an array of dataqsiz elements
elemsize uint16
closed uint32
elemtype *_type // element type
sendx uint // send index
recvx uint // receive index
recvq waitq // list of recv waiters
sendq waitq // list of send waiters
// lock protects all fields in hchan, as well as several
// fields in sudogs blocked on this channel.
//
// Do not change another G's status while holding this lock
// (in particular, do not ready a G), as this can deadlock
// with stack shrinking.
lock mutex
}
可以看到,有lock欄位,在使用channel進行傳送和接收的時候,會進行加鎖保護。
參考
雨痕《Go學習筆記 第四版》