channel是golang里很重要的一种数据结构

channel的特性

0QRSAO.jpg

channel内部实现

buffered channel在底层使用一个struct来实现,使用一个环形缓冲区circular queue来保存元素。

0QRMCQ.jpg

向channel发送值
0QRU5F.jpg

channel的buffer已满

0QRdC4.jpg

从channel接收值
0QRcVK.jpg

ps:
0QRh2d.jpg
使用make来创建channel时,go在堆上分配一个hchan struct,然后初始化它,最后返回的是一个指向hchan struct的指针。

channel发送和接收值的过程

buffered channel之所以能够goruntine安全,因为每次sendreceive时,都会对结构体内的mutex上锁。

下面是send的过程。
0QWkiF.jpg
0QWiIU.jpg
0QWPaT.jpg

下面是receive的过程。

0QW8RH.jpg
0QW3Je.jpg
0QW1iD.jpg

channel如何暂停(Pause)和恢复(Resume) goroutine

0lCoV0.jpg

先了解下Go的调度器和GMP

0lPJLn.jpg

goroutine可以看做是用户态线程,goroutine由go运行时创建和管理,被调度器调度到系统线程。

0lPxSg.jpg

暂停(Pause)goroutine

0li3tK.jpg

可以看到,当channel满时,被阻塞的只是goroutine,系统线程仍处在运行状态。

恢复(Resume)goroutine

01cS4e.jpg

01cC3d.jpg

当从一个满的channel接收值时

01cwvR.jpg

01cuCQ.jpg

01cZE8.jpg

01ceUS.jpg

01cm4g.jpg

参考资料

GopherCon 2017: Kavya Joshi - Understanding Channels
Kavya Joshi - Understanding Channels.pdf

Last modification:October 3rd, 2020 at 10:35 am
如果觉得我的文章对你有用,请尽情赞赏 🐶