go源碼分析-> channel

針對go語言中chan的源碼分析channel的機制

1:發送者流程
1:常規檢查(發送一個已經關閉的chan會直接觸發panic)
2:查看接受則阻塞隊列中是否有sudog(對應的一個goroutine,注意是dequeue操作),如果有則直接發送消息到阻塞的goroutine(gp.param = unsafe.Pointer(sg),直接進行指針賦值,具體見chan.go/send函數),並且喚醒接受goroutine,goto 6
3:如果當前的阻塞隊列沒有滿(sudog數量),則直接將發送的數據寫入到發送的隊列上(追加寫),goto 6
4:當前的的阻塞隊列滿了(緩衝的數量在此處對於等待隊列中goroutine的數量),生成一個sudog,將當前的goroutine加入的發送者隊列中,阻塞當前goroutine,直接有消費者消費完消息
5:阻塞結束,釋放當前的sudog
6:over

2:接受者流程
1:常規檢查(接收一個已經關閉的chan會直接return)
2:查看接受則阻塞隊列中是否有sudog(對應的一個goroutine),如果有則直接接受消息對於sudog的消息,goto 6
3:檢查緩衝隊列中是否有數據,有就直接取 goto 6; 否則繼續
4:(進入阻塞,條件是1:發送隊列中沒有sudog,2:緩衝區沒有數據)將當前sudog加入接受等待隊列中,並阻塞當前goroutine(調用goparkunlock)
5:阻塞結束,釋放當前的sudog
6:over

3:channel關閉流程
1:常規檢查
2:遍歷發送者/接受者隊列中阻塞sudog,清空elem
3:喚醒對於sudog對於的goroutine

//sudog解釋:
//一個sudog對應的一個發送/接受消息的goroutine
type sudog struct {
	g *g //當前的goroutine
	isSelect bool //是否阻塞
	next     *sudog //鏈表信息
	prev     *sudog
	elem     unsafe.Pointer // data element (may point to stack) //元素指針
	acquiretime int64
	releasetime int64
	ticket      uint32
	parent      *sudog // semaRoot binary tree
	waitlink    *sudog // g.waiting list or semaRoot 阻塞信息
	waittail    *sudog // semaRoot
	c           *hchan // channel
}

ps:至於有緩衝和無緩衝(緩衝區0)的區別,直接套流程就知道區別了。

ps:源碼位置go/src/runtime/chan.go

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章