chan

数据结构

类似于管道,可以并发读写。不可以向已关闭chan写入数据。

// 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
    sendx    uint   // send index
    recvx    uint   // receive index

    elemsize uint16
    closed   uint32
    elemtype *_type // element type

    // 读写等待队列
    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
}

实现

直接搬运代码,专注细节容易绕晕。大致每个功能需要考虑几种边界条件

阻塞/非阻塞
缓冲区为空/非空
缓冲区满/非满
读写等待队列空/非空
chan为nil/非nil

1、单chan读/写(runtime/chan.go:chanrecv/chansend)


2、关闭chan(runtime/chan.go:closechan)。加锁;唤醒读/写等待队列全部任务;解锁

3、多个chan同时读/写(runtime/select.go:selectgo)。大致思路就是打乱case顺序;对全部chan加锁;遍历找出第一个读/写准备好的任务;逆序解锁

你可能感兴趣的:(chan)