channel

Written by with ♥ on in Go

概述

了解 channel 背后的设计原理以及底层数据结构。channel 在底层依旧通过 mutex 控制并发,提供更高层次的抽象。

数据结构

底层结构:

type hchan struct {
    qcount   uint // channel 中元素个数
    dataqsiz uint // 循环队列的长度
    buf      unsafe.Pointer // 指向一个长度为 dataqsiz 的底层循环数组,值针对有缓冲的 channel
    elemsize uint16 // 当前 channel 收发的元素大小
    closed   uint32 // 是否关闭的标志
    elemtype *_type // 当前 channel 能够收发的元素类型
    sendx    uint // 标识当前 channel 的发送处理到数组中的哪个位置,send index
    recvx    uint // 标识当前 channel 的接收处理到数组中的哪个位置,recv index

    recvq    waitq // 存储当前 channel 由于缓冲区空间不足而阻塞的 goroutine 列表,这些 goroutine 由于尝试读取 channel 数据而阻塞
    sendq    waitq // 存储当前 channel 由于缓冲区空间不足而阻塞的 goroutine 列表,这些 goroutine 由于尝试向 channel 写入数据而阻塞

    lock mutex
}

type waitq struct {
    first *sudog
    last  *sudog
}

sudog 是一个运行时的结构体的,它的主要作用就是表示一个在等待列表中的 goroutine,其中存储着关于这一次阻塞的信息以及两个分别指向前后的 sudog 指针。

基本操作

创建

ch := make(chan int, 1)