channel
单纯将函数并发是没有意义的.函数与函数间需要交换数据才能体现并发执行的意义.
共享内存进行数据交换会导致goroutine
发生竞态问题.为了保证数据交换的正确性,必须使用互斥量对内存进行加锁,这种做法势必会导致阻塞问题.
Go语言的并发模型是CSP(Communicating Sequential Process)
,提倡通过通信共享内存而不是通过共享内存而实现通信.
如果说goroutine
是Go程序并发的执行体,channel
就是它们之间的连接.channel
是一个可以让一个goroutine
发送特定值到另一个goroutine
的通信机制.
Go语言中的通道(channel)是一种特殊的类型.通道像一个队列,遵循FIFO原则.每一个通道都是一个具体类型的的导管,也就是声明channel的时候需要为其指定元素类型.
channel类型
var 变量 chan 元素类型
例:
var ch1 chan int // 声明一个传递整形的通道
var ch2 chan bool // 声明一个传递布尔型的通道
var ch3 chan []int // 声明一个传递int切片的通道
创建channel
通道是引用类型,通道类型的空值是nil
var ch chan int
fmt.Println(ch) // nil
// 声明channel后需要使用make函数初始化之后才能使用.创建channel的格式:
make(chan 元素类型, [缓冲大小])
ch1 := make(chan int) // 不带缓冲区的通道初始化
ch2 := make(chan bool, 16) // 带缓冲区的通道初始化
ch3 := make(chan []int)
channel信息传递
发送
ch <- 10 // 把10发送到ch中
接收
x := <- ch // 从ch中接收值并赋值给变量x
<-ch // 从ch中接收值,忽略结果
关闭
close(ch)
单向通道
func f(ch chan<- int) // 声明f()中,ch只能作为写入通道
func f(ch <-chan int) // 声明f()中,ch只能作为读取通道
channel总结
channel
常见异常总结
channel异常情况总结 | |||||
---|---|---|---|---|---|
channel | nil | 非空 | 空的 | 满了 | 没满 |
接收 | 阻塞 | 接收值 | 阻塞 | 接收值 | 接收值 |
发送 | 阻塞 | 发送值 | 发送值 | 阻塞 | 发送值 |
关闭 | panic | 关闭成功,读完数据后返回零值 | 关闭成功,返回零值 | 关闭成功,读完数据后,返回零值 | 关闭成功,读完数据后,返回零值 |
关闭已经关闭的channel
,也会触发panic
worker pool (goroutine池)
编写代码实现一个计算随机数的每个位置之和的程序,要求使用goroutine
和channel
构建生产者和消费者模式,可以指定启动的goroutine数量:worker pool
模式。
工作中通常使用worker pool
模式,控制goroutine
的数量,防止 goroutine
泄露和暴涨。