前言

Go语言中实现了两种并发模型,一种是我们熟悉的线程与锁并发模型,它主要依赖于共享内存实现。另一种是Go语言中倡导使用的CSP(communicating sequential process)通信顺序进程模型。它最初由Tony Hoare于1977年的论文中被提出。

CSP类似于我们常用的同步队列,它关注的是消息传输的方式,即通道,而并不关注消息的具体发送实体和具体接受实体。同时它也极容易导致死锁,如果一个并发实体在读取一个永远没有数据放入的通道或者把数据放入一个用于不会被读取的通道中,那么它将被永远阻塞,也就是死锁。

声明

1
2
var channelName chan T
ch1 := make(chan int, 1)

我们通过chan关键字声明了一个新的channel,并且声明时指定channel内传输的数据类型T。

channel的发送与接收

channel作为一个队列,它会保证数据收发顺序总是遵循先入先出的原则进行,同时它也会保证在同一时刻内有且仅有一个goroutine访问channel来发送和获取数据。

写操作

这段代码表示val将被发送到channel中,在channel被填满之后再向通道中发送将会阻塞当前goroutine。

1
channel <- val

读操作

这段代码表示从channel中读取一个值并赋值到val上,如果channel中没有数据,将会阻塞读取的goroutine,直到有数据被放入channel。

1
val := <- channel

我们可以在读取数据时使用一个额外的bool返回值判断当前channel是否关闭:

1
2
3
4
5
6
7
//由于在channel关闭时,其val默认值也会为0,需要通过ok来判断channel是否关闭。
ch <- 0
if val, ok := <-ch; ok{
//chan:open
}else{
//chan:close
}

有缓冲channel

缓冲 channel 是指在发送数据和接收数据之间,发送方和接收方不一定同时准备好。缓冲 channel 允许在发送操作和接收操作之间存在一定的时间差。
缓冲 channel 的容量大于 0,即可以存储一定数量的数据。
缓冲 channel 的主要特点是 异步性,它允许发送方和接收方在一定程度上解耦,发送方可以继续发送数据,而不需要等待接收方立即接收。

无缓冲channel

无缓冲 channel 是指在发送数据和接收数据之间,发送方和接收方必须同时准备好。即发送操作和接收操作必须在同一个时间点上发生,否则两个协程都会被阻塞。
无缓冲 channel 的容量为 0,即不能存储任何数据。
无缓冲 channel 的主要特点是 同步性,它保证了发送方和接收方的同步操作。