第十六篇:协程通信之认识channel、死锁、多协程速度比较
引言:
func sum(max int){
result:=0
for i:=1;i<=max;i++{
result=result+i
}
fmt.Println(result)
}
func main(){
go sum(100)
/*
直接运行是没有输出的,因为main函数已经运行结束了,但是go的sum
函数还在 执行,还没有结束;
所以如果有输出结果,可以在main函数中,加上延迟时间
*/
time.Sleep(time.Second)
但是上述代码,使用time包的sleep 我们无法"完美的" 解决协程执行顺序的问题,执行顺序问题,我们要使用协程间的通信;
一:协程之间的通信(channel类型)
这是go里面的核心数据类型,有了它,我们可以方便的进行协程间的数据通信,其原理来源于CSP模型理论,go实现了部分理论;
简单来说,CSP模型由并发执行的实体(如进程或线程)组成,实体之间通过发送消息进行通信,其中channel承担了实体和实体之间发送消息的通道;
在go里面goroutine就是实体.它里面也有个channel来完成通信;
func sum(max int,c chan int){
result:=0
for i:=1;i<=max;i++{
result=result+i
}
c <- result //发送数据到我们的通道 发送者
}
func main(){
//开辟管道,int类型(因为go调用的函数返回结果为int类型)
c:=make(chan int)
go sum(10000,c)
//go 协程调用 传递管道c之后,必须要有接收,否则会有死锁
ret:=<- c //取出管道中的数据 接收者
fmt.Println(ret)
//至此就完成了 我们主线程main和协程之间的数据传递的过程
二:阻塞
上面的代码中
对于发送者:如果没有接收者读取channel (<- channel),则发送者(channel <-)会一直阻塞
对于接收者:接收操作是阻塞的直到发送者发送数据
根据上面的特性,就能实现当goroutine执行完成后,得到数据
三:死锁

四:带缓冲的channel
刚才我们创建的是 c:=make(chan int)
注意其实还有参数 c:=make(chan int,2)
这好比创建一个 带有容量为2的channel(好比队列)
(1):只有当队列塞满时发送者会阻塞;

(2):队列空时接收者会阻塞

五:任务拆分的累加练习

反复练习代码的书写,防止死锁的发生

浙公网安备 33010602011771号