Golang在并发编程上有两大利器,分别是channel和goroutine。Golang中有一句名言:“使用通信来共享内存,而不是通过共享内存来通信”。这句话有两层意思,Go语言确实在sync包中提供了传统的锁机制,但更推荐使用channel来解决并发问题。这里先对Channel做一个基本的介绍,对于其深一层的实现原理,等今后有空了再学习总结一下。
u 什么是Channel
从字面上理解,channel的意思是管道。它是一种go协程用以接收或发送消息的安全的消息队列。channel就像两个go协程之间的导管,来实现各种资源的同步。如图示意:
Channel 是进程内的通信方式,因此通过 channel 传递对象的过程和调用函数时的参数传递行为比较一致,比如也可以传递指针等。使用channel发送和接收所需的共享资源,可以在 goroutine 之间消除竞争条件。Channel 是类型相关的,也就是说,一个 channel只能传递一种类型的值,这个类型需要在声明 channel 时指定。
u Channel的类型以及有无缓冲的channel
channel类型的定义格式如下:
ChannelType = ( "chan" | "chan" "<-" | "<-" "chan" ) ElementType .
它包括三种类型的定义。可选的<-
代表channel的方向。如果没有指定方向,那么Channel就是双向的,既可以接收数据,也可以发送数据:
chan T // 可以接收和发送类型为 T 的数据
chan<- float64 // 只可以用来发送 float64 类型的数据
<-chan int // 只可以用来接收 int 类型的数据
<-
总是优先和最左边的类型结合:
chan<- chan int // 等价 chan<- (chan int)
chan<- <-chan int // 等价 chan<- (<-chan int)
<-chan <-chan int // 等价 <-chan (<-chan int)
chan (<-chan int)
使用make初始化Channel,并且可以设置容量:
make(chan int, 100)
容量代表channel容纳的最多的元素的数量,代表Channel的缓存的大小。如果没有设置容量,或者容量设置为0, 说明Channel没有缓存,只有sender和receiver都准备好了后它们的通讯才会发生。如果设置了缓存,就可能不发生阻塞,只有buffer满了后 send才会阻塞,而只有缓存空了后receive才会阻塞。一个nil channel不会通信。这就构成了所谓的Unbuffered Channels和Buffered Channels:
² Unbuffered Channels
指缓冲区大小为0的channel,接收者会阻塞直至接收到消息,发送者会阻塞直至接收者接收到消息,这种机制可
用于两个goroutine进行状态同步。下图可以形象说明两个goroutine如何利用无缓冲的channel来共享
一个值(下图来自互联网):
² Buffered Channels
指缓冲区大小不为0的channel,当缓冲区已满时,发送者会阻塞;当缓冲区为空时,接收者会阻塞。
这种类型的通道并不强制要求goroutine 之间必须同时完成发送和接收。这导致有缓冲的通道和无缓冲的通道之间的一
个很大的不同:无缓冲的通道保证进行发送和接收的 goroutine 会在同一时间进行数据交换;有缓冲的通道没有这种
保证。
同样可以以下图来展示:
标签:缓冲,goroutine,chan,阻塞,Golang,Channel,channel From: https://www.cnblogs.com/gongxianjin/p/17535123.html