Go语言并发编程基础 | 青训营笔记

112 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天
今天读了读《Go语言圣经》的第8章,简单写一写笔记,方便后面的复习和继续学习。

Goroutines

在Go中,每一个并发的执行单元叫做一个goroutine,可以简单的将其类比为一个线程,但是它们还是有本质区别

一个程序启动时,其主函数就是在一个单独的goroutine中运行,新的goroutine由go func()创建, func()是一个函数或者方法。

当主函数返回或者主程序直接终止时,所有的goroutine都会被打断。

Channels

channels是goroutine之间的通信机制(类似管道 pipe)。

ch := make(chan int) //一个可以发送int类型数据的channel,变量名为ch

channel对应一个make创建的底层数据结构的引用。因此复制一个channel或者用于函数的参数传递时,只是拷贝一个channel引用,调用者和被调用者将引用同一个channel对象。

使用<-发送和接收,close()关闭channel,例如:

ch <- x   //x通过channel发送
y = <- ch //y从channel接收
close(cn) //关闭channel

无缓存的Channels

ch := make(chan int)是无缓冲的channel,当一个goroutine执行发送操作时,会使发送者goroutine阻塞,直到另一个goroutine在同一个channel上执行接收操作。

这个操作使得两个goroutine做一次同步操作,所以无缓存的channels又称为同步channels。

串联Channels(Pipeline)

将一个channel的输出作为下一个channel的输入,就是串联的Channels,即所谓pipeline。

书中ch8有关pipeline的代码让我想起了6.S081的一个实验,Lab: Xv6 and Unix utilities (mit.edu)中的primes实验,二者有异曲同工之妙。当时折磨了我好久😢

单方向的Channels

可能存在这样一种场景,只需要发送或者接收消息。因此Go语言也提供了单方向的channel类型。

类型chan<- int表示一个只发送int的channel,只能发送不能接收。相反,类型<-chan int表示一个只接收int的channel,只能接收不能发送。

箭头和关键字chan的相对位置表示方向,将会在编译器检测。例:

ch := make(chan<- int)

有缓存的Channels

ch := make(chan string, 3)// 创建一个可以持有三个字符串元素的带缓存的channel

向缓存Channel的发送操作就是向内部缓存队列的尾部插入元素,接收操作则是从队列的头部删除元素。

如果内部缓存队列是满的,那么发送操作将阻塞直到因另一个goroutine执行接收操作而释放了新的队列空间。

相反,如果channel是空的,接收操作将阻塞直到有另一个goroutine执行发送操作而向队列插入元素。

缓存队列的大小就是make中第三个参数设置的大小。

cap(ch)会返回channel内部缓存的容量(Capacity)。len(ch)会返回channel内部缓存队列中有效元素的个数(Length)。

参考资料

Goroutines和Channels · Go语言圣经 (studygolang.com)