在看本篇文章前我们需要了解阻塞的概念
- 在执行过程中暂停,以等待某个条件的触发 ,我们就称之为阻塞
在Go中我们make一个channel有两种方式,分别是有缓冲的和没缓冲的
- 缓冲
channel即buffer channel创建方式为make(chan TYPE,SIZE)- 如
make(chan int,3)就是创建一个int类型,缓冲大小为3的channel
- 如
- 非缓冲
channel即unbuffer channel创建方式为make(chan TYPE)- 如
make(chan int)就是创建一个int类型的非缓冲channel
- 如
- 非缓冲
channel和 缓冲channel的区别- 非缓冲
channel,channel发送和接收动作是同时发生的 - 例如
ch := make(chan int),如果没goroutine读取接收者<-ch,那么发送者ch<-就会一直阻塞 - 缓冲
channel类似一个队列,只有队列满了才可能发送阻塞
- 非缓冲
代码演示
非缓冲
channel
package main
import (
"fmt"
"time"
)
func loop(ch chan int) {
for {
select {
case i := <-ch:
fmt.Println("this value of unbuffer channel", i)
}
}
}
func main() {
ch := make(chan int)
ch <- 1
go loop(ch)
time.Sleep(1 * time.Millisecond)
}
- 这里会报错
fatal error: all goroutines are asleep - deadlock!就是因为ch<-1发送了,但是同时没有接收者,所以就发生了阻塞 - 但如果我们把
ch <- 1放到go loop(ch)下面,程序就会正常运行
- 缓冲
channel的阻塞只会发生在channel的缓冲使用完的情况下
package main
import (
"fmt"
"time"
)
func loop(ch chan int) {
for {
select {
case i := <-ch:
fmt.Println("this value of unbuffer channel", i)
}
}
}
func main() {
ch := make(chan int,3)
ch <- 1
ch <- 2
ch <- 3
ch <- 4
go loop(ch)
time.Sleep(1 * time.Millisecond)
}
- 这里也会报
fatal error: all goroutines are asleep - deadlock!,这是因为channel的大小为3,而我们要往里面塞4个数据,所以就会阻塞住 - 解决的办法有两个
- 把
channel开大一点,这是最简单的方法,也是最暴力的 - 把
channel的信息发送者ch <- 1这些代码移动到go loop(ch)下面 ,让channel实时消费就不会导致阻塞了
- 把
版权声明:本文为qq_36431213原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。