Go语言之channel实现原理

背景

在写代码的时候,我们很多时候都会用到channel,但是channel是如何实现的呢?

基于上一篇文章

Go语法实现分析之chan、go func、类型转换_程序员红豆的博客-CSDN博客声明、初始化代码,我们都懂,但是它背后是怎么实现的呢?https://blog.csdn.net/qq_37186127/article/details/125521611我们来分析分析channel的实现

过程

我们先看chan.go的hchan结构

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
}

qcount:channel当前的数据总数

dataqsiz:channel的大小

buf:用于存储数据的环形队列指针

closed:是否已经关闭

sendx:发送索引

recvx: 接收索引

recvq:当缓冲信道接收阻塞的时候,用于挂载sudog

sendq: 当缓冲信道发送阻塞的时候,用于挂载sudog

无缓冲信道就没什么好了解的了,因为直接阻塞

我们接下来看下有缓冲信道是怎么实现的

缓冲信道(channel)发送的内部实现

Go语言之channel实现原理_第1张图片

 我们可以看到,当我们向ch发送两条数据的时候,qcount变成了2,buf里面多了7、8两个元素

sendx也变成了2,意味着下一次发送进来的数据是存储到buf[2]这里

Go语言之channel实现原理_第2张图片

 上述代码初始化了一个容量大小为3的信道,并且向信道发送了3个数据

这时候channel是数据是满了,那么接下来的数据发送就会进行阻塞

我们可以发现qcount变成了3,sendx变成了0

那么阻塞的数据channel会如何处理呢?

Go语言之channel实现原理_第3张图片

阻塞的数据会形成一个sudog被挂到sendq数据结构下

Go语言之channel实现原理_第4张图片

 缓冲信道(channel)接收的内部实现

Go语言之channel实现原理_第5张图片

 如果我们从一个空channel里接收数据,那么也会形成阻塞[1],并形成一个sudog,挂到recvq下

Go语言之channel实现原理_第6张图片

如果我们从buf中消费一个数据的时候,recvx也会随之改变

本文完~

扩展阅读 

Go是如何处理goroutine阻塞的?_程序员红豆的博客-CSDN博客

你可能感兴趣的:(Golang,golang)