go语言并发编程下
上文从基础层面讲解了goroutine 和 channel ,关于如何使用都停留下嘴皮子上,因此下篇选用几个最简单的例子来巩固下。另外推荐下自己的个人博客,你可以先点进行看下内容是否对您有帮助,在选择收藏或者直接x掉。
个人博客地址:Colourful Code
正文
首先,上文说到channel 有两种情况:
未分配缓存
分配一定缓存
例子从这两点入手给出。
未分配缓存
package main
import "fmt"
//求和函数sum
func sum(a []int,c chan int){
sum :=0
for _,v := range a{
sum += v
}
c<-sum //向通道c 写入数据值 sum
}
//主程序入口
func main(){
a:= []int{1,3,5,2,-2}
c:= make(chan int)
go sum(a[:],c) //开辟一个goroutine 用于进行sum函数执行
x:= <-c //读取c通道的值赋值给x
fmt.Println(x)
}
从主程序开始分析,如下分为几个步骤:
声明定义了一个数组 a
声明定义了一个通道 c,注意是没有给定缓存的。
正因为加了go关键字 ,所以为sum函数开辟一个goroutine,同时给函数传入参数:数组a和通道c。这个时候程序除了主routine,也就是main函数。与此同时还有为sum开辟的子routine,这个子routine所要做的就是对传入的数组进行求和,并且将结果值写入通道c中。
主routine执行完
go sum(a[:],c)
这条语句之后,马上就可以执行下一条语句了。也就是x:=<-c
。 这里就有点意思了。要根据实际情况分2种情况来说:c 通道有值和无值。- c 通道有值,这意味着子goroutine 中进行的求和运算先完成,通过语句
c<-sum
将结果值写入通道时,由于完成的太早,没有接收方从通道读取数据造成了堵塞,子routine中的程序卡死在这里,等待接收者读取数据。直到主routine执行了x:=<-c
这条语句,顺利的从通道读取到了数据,于此同时子routine中c<-sum
由于通道数据被读走,这里不再堵塞,子routine中的sum函数执行完毕。 - c 通道没有值,意味着子goroutine 中进行的求和运算还未完成(假如这里的求和运算改为大数据处理,我想要花费很多时间。),数据还未写入到c通道中,因此由于通道内没有数据,主routine中会堵塞在
x:=<-c
这条语句上,等待子routine完成数据计算,执行c<-sum
语句往通道中写数据。这时候主routine中 顺利读取通道c中的值,赋值给x,打印出来。
- c 通道有值,这意味着子goroutine 中进行的求和运算先完成,通过语句
分配缓存
package main
import "fmt"
func main(){
c:=make(chan int,2)
c <- 10
c <- 20
fmt.Println(<-c)
fmt.Println(<-c)
}
由于理解了channel 工作机制,那么分配缓存理解起来容易一些。
首先声明定义一个缓存大小为2的特定类型为int的通道c
往通道写入值10,想一想,倘若没有分配缓存,那么程序会堵塞在这里,除非其他routine会从该通道读取数据,但这显然不可能,因为这时候是在主routine中,你又没有创建子routine,所以最后只会报错,“all goroutines are asleep - deadlock!”
这时候你应该已经理解了,正因为分配了缓存,因此能够顺利的写入值10,接下来往通道写入值20,显然由于缓存还有空间,写入没有问题,不会造成堵塞,程序继续执行下去!
<-c
就是从通道中读取数据,会打印10打印20,有种FIFO(注:“first in first out”,先入先出)的感觉,由于我们往通道缓存中写入值10,再写入值20,取出时就应该有顺序的先取出值10,再取出值20。
结尾:
博主是一个刚入坑的go小菜鸟,对go语言理解可能还不是很透彻,倘若哪里理解不对,或者写的有问题,欢迎指正,踩踩更健康嘛,不过希望您能留言告诉我为啥踩的理由吗,好让我改正,这也算一种学习不是吗?最后谢谢!