七叶笔记 » golang编程 » Golang并发编程,4、无缓冲通道和有缓冲通道的区别

Golang并发编程,4、无缓冲通道和有缓冲通道的区别

channel是Go语言中的一个核心数据类型,负责go协程的2个问题:(1)同步问题;(2)协程之间数据共享(数据传递)。

goroutine 通过通信来共享内存,而不是共享内存来通信。

一、无缓冲通道

1、 声明一个无缓冲通道时,不需要声明容量。

在没有准备就绪的接收者的时候,第一个 goroutine 在发送消息后channel将被阻塞。

如果通道是无缓冲的,发送者将被阻塞,直到接收者接收到值。

2、声明无缓冲通道

 var ch = make(chan int)  

3、定义1个函数,循环输出10次。

len(ch):表示使用了xx个通道

cap(ch):表示还剩下xx个通道

 func User1() {
   for i := 0; i < n; i++ {
      ch <- i
      fmt.Printf("User1协程正在运行 , 经历了 %v 秒,使用了%v个,还剩%v个 \n", i, len(ch), cap(ch))
   }
}  

4、在主函数中,建子协程,运行函数user1。

循环获取通道内的数值,由于是无缓冲通道,那么就等待子协程传递进来1个后,才可以继续执行顺序代码。

 go User1()
for i := 0; i < n; i++ {
   x := <-ch
   time.Sleep(time.Second * 1)
   fmt.Printf("当前管道内的值是:%v\n", x)
}  

5、执行结果

可以看到,在无缓冲通道的时候,channel内,使用和剩余管道内始终为0,因为通道内在没有阻塞的时候,通道内是不存在数据的。

因此代码才是进通道1个数据后,等待从通道内取走数据,否则将等待;当数据取走后,通道才可以有接受新数据的能力。

二、有缓冲通道

1、 声明一个有缓冲通道时,需要提前声明通道的容量。

当通道是有缓冲时,发送者将数据持续发到通道内,直到达到容量最大值,后才被阻塞,直到接收者接收到值,每当接受1个值后,通道腾出1个位置继续接受传递进去的值。

2、创建1个有缓冲通道,缓存容量为1

 var c = 1
var ch = make(chan int, 1)  

3、定义1个函数,循环输出10次。

len(ch):表示使用了xx个通道

cap(ch):表示还剩下xx个通道

 func User1() {
   for i := 0; i < n; i++ {
      ch <- i
      fmt.Printf("User1协程正在运行 , 经历了 %v 秒,一共%v个通道,使用了%v个,还剩%v个 \n", i, c, len(ch), cap(ch))
   }
}  

4、在主函数中,建子协程,运行函数user1。

循环获取通道内的数值,由于是有缓冲通道,那么就等待子协程传递进来1个后,才可以继续执行顺序代码。

 func main() {
   go User1()
   for i := 0; i < n; i++ {
      x := <-ch
      time.Sleep(time.Second * 1)
      fmt.Printf("当前管道内的值是:%v\n", x)
   }
}  

5、执行结果

可以看到,在有缓冲通道的时候,channel内,每当执行1次,通道内可用容量减1,直到最大容量时,等待从通道内取走数据,通道阻塞。当数据取走后,通道才可以有接受新数据的能力。

源码

相关文章