This page looks best with JavaScript enabled

How Channel Works

 ·  ☕ 1 min read

How channel works

Note of
https://www.youtube.com/watch?v=KBZlN0izeiY&ab_channel=GopherAcademy
by Kavya Joshi.

Channel !!!

goroutine-safe
store data、FIFO
pass data between goroutines
block, unblock goroutine

making channels

https://golang.org/src/runtime/chan.go

  • hchan struct contains
    buf -> circular queue (with send index & receive index)
    sendx
    recvx
    mutex
    sendq // list of sudo g
    recvq // list of sudo g

ch := make(chan Task, 3)
This comman allocates an hchan on the heap
ch is a pointer to hchan

sends and receives

sender sends

  1. acquires lock
  2. put a copy of data into channel buf
  3. releases lock

no shared memory except hchan between goroutines

what if a sender trys to send data into a full channel?

Sender (G1), Receiver(G2)

Sender G1
G1 creates a sudog(of itself, this contains goroutine pointer and data) and puts it into the sendq.

G1 calls the scheduler to detach(gopark) G1 from the M and set G1 to waiting state.
Then the scheduler pops a runnable G from runq and schedules it to run on the M.

Sender is blockd but not the OS thread.

How to resume?
Receiver
Get an element from channel buf then pops a sudog from sendq.
Enqueue data(in poped sudog) into buf.
Calls into the scheduler to set the waiting sender(G1) to runnable and put it in runq of P(or global queue).
Returns to Receiver

what if a receiver trys to receive data on an empty channel?

Sender (G1), Receiver(G2)

Receiver
G2 puts a sudog into recvq then call gopark to detach from M.

Sender
G1 enqueue data into the buf, and call goready???
No,
G1 writes to memory location of G2 directly
G1 writes to G2’s stack
G2 does not need to access the channel, and fewer memory copy

design considerations

simplicity

queue + lock v.s. lock-free

performance

So threads not blocked

cross-goroutine stack & reads writes

goroutine wake up is lockless

fewer memory copy

others

nbufferd channel: read and write directly to each other’s stack

select: put the current goroutine to sendq and recvq of the channels in cases then call scheduler.

Share on

Marko Peng
WRITTEN BY
Marko Peng
Good man