owned this note changed 4 years ago
Linked with GitHub

使用Go channel的正確姿勢 - Gaston Chiu

tags: COSCUP2020 入門 TR214

歡迎來到 https://hackmd.io/@coscup/2020 共筆

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

點擊本頁上方的 開始用 Markdown 一起寫筆記!
手機版請點選上方 按鈕展開議程列表。

請從這裡開始

Channel 101

base on CSP (Communication Sequential Process)

  • Passing, no share state

channel 可能是 Circular Queue + Mutex Lock ?

Blocking

make(chan int) == make(chan int, 0)

  • chl is empty when receive
  • chl is full and no buffer when send

Non-blocking

make(chan int, n)

  • chl has buffer when send
  • select with default

channel 帶有 buffer 可以提高吞吐量,而提升效能

Go scheduler

G:
M:
P:

Dive into channel implementation

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
}
  • Recvq, Sendq 是去紀錄要等待存取的 send/receive requests as linked list
    • request entry includes
      • data
      • a go routine (which put/get data)
      • pointer to next entry
    • send request copy data to recieve requst directly if there's one waiting in queue
    • goready, gopark

select 的順序是無意義的,其實作是隨機去拿在 case 中的 channel

講者提到可以寫如下的程式去提高被選到的機率

select {
case y := <- ch1:
    doA(y)
case y := <- ch2:
    doB(y)
case y := <= ch2:
    doB(y)
case y := <= ch2:
    doB(y)
default:
    doC()
}
Select a repo