第十六篇:协程通信之认识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):队列空时接收者会阻塞

  

 

 五:任务拆分的累加练习

  

 

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

 

  

  

  

  

  

  

  

posted @ 2020-06-10 14:51  痞子胥  阅读(306)  评论(0)    收藏  举报