今天看啥  ›  专栏  ›  LitC

Channel(一)chan数据结构

LitC  · 简书  ·  · 2021-03-12 08:58

chan数据结构

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 接收消息goroutine队列,链表 
    sendq waitq // list of send waiters 发送消息goroutine队列,链表 
    // 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 
}

环形队列

创建有缓冲区channel时,如下:

channel := make(chan int, 6) //6: 指定了channel的环形队列大小
image.jpeg

等待队列

channel读写操作:

  • 读:无缓冲区或缓冲区空,读goroutine阻塞,被挂起在channel的recvq队列中,直到被写goroutine唤醒
  • 写:无缓冲区或缓冲区满,写goroutine阻塞,被挂起在channel的waitq队列中,直到被读goroutine唤醒

无缓冲区的channel结构如下:G阻塞读取数据

image.jpeg

数据结构

//双向链表
type waitq struct {
   first *sudog
   last  *sudog
}
 //被阻塞的goroutine的封装
type sudog struct {
   // The following fields are protected by the hchan.lock of the
   // channel this sudog is blocking on. shrinkstack depends on
   // this for sudogs involved in channel ops.

   g *g

   next *sudog
   prev *sudog
  elem unsafe.Pointer // data element (may point to stack)

   // The following fields are never accessed concurrently.
   // For channels, waitlink is only accessed by g.
   // For semaphores, all fields (including the ones above)
   // are only accessed when holding a semaRoot lock.

   acquiretime int64
   releasetime int64
   ticket      uint32

   // isSelect indicates g is participating in a select, so
   // g.selectDone must be CAS'd to win the wake-up race.
   isSelect bool

   parent   *sudog // semaRoot binary tree
   waitlink *sudog // g.waiting list or semaRoot
   waittail *sudog // semaRoot
   c        *hchan // channel
}

类型信息

一个channel只能用于一种数据类型

  • elemsize:标识元素大小,用于定位
  • elemtype:标识元素类型

lock实现锁:

  • 消费者互斥读
  • 生产者互斥写



原文地址:访问原文地址
快照地址: 访问文章快照