有缓冲的通道
是一种在被接收前能够存储一个或多个值的通道
这种类型的通道并不强制要求goroutine之间必须同时完成发送和接收。通道会阻塞发送和接收动作的条件也不同。只有在通道中人没有要接收的值时,接收动作才会阻塞。只有在通道没有可用缓冲区容纳被发送的值时,发送动作才会阻塞。
&ensp这导致有缓冲的通道和无缓冲的通道之间一个很大的不同,无缓冲的通道保证进行发送和接收的goroutine会在同一时间进行数据交换;有缓冲的通道没有这种保证。
有缓存的channel
通过图片了解无缓存的channel
第一步:右侧的goroutine正在从通道接收一个值。
第二步:右侧的这个goroutine独立完成了接收值得动作,而左侧的goroutine正在发送一个新值到通道里。
第三本步:左侧的goroutine还在向通道发送新值,而右侧的goroutine正在从通道接收另外一个值,这个步骤里的两个操作既不是同步,也不会互相阻塞。
第四步:所有的发送和接收都完成,而通道里还有几个值,也有一些空间可以存更多的值。
有缓存的channel创建格式
make(chan Type,capacity)
package main
import (
"fmt"
"time"
)
func main() {
//创建一个有缓存的channel
ch := make(chan int, 3)
//len(ch)缓冲区剩余数据个数,cap(ch)缓冲区大小
fmt.Printf("len(ch) = %d , cap(ch) = %d \n", len(ch), cap(ch))
//新建协程
go func() {
for i := 0; i < 3; i++ {
ch <- i //往chan写内容
fmt.Printf("子协程[%d]:len(ch) = %d,cap(ch) = %d\n", i, len(ch), cap(ch))
}
}()
//延时
time.Sleep(2 * time.Second)
for i := 0; i < 3; i++ {
num := <-ch //读管道中内容,没有内容前,阻塞
fmt.Println("num = ", num)
}
}
#结果,运行更能看出效果,尤其是主协程受延时的影响
len(ch) = 0 , cap(ch) = 3
子协程[0]:len(ch) = 1,cap(ch) = 3
子协程[1]:len(ch) = 2,cap(ch) = 3
子协程[2]:len(ch) = 3,cap(ch) = 3
num = 0
num = 1
num = 2
容量与延时,与阻塞的关系
package main
import (
"fmt"
"time"
)
func main() {
//创建一个有缓存的channel
ch := make(chan int, 3)
//len(ch)缓冲区剩余数据个数,cap(ch)缓冲区大小
fmt.Printf("len(ch) = %d , cap(ch) = %d \n", len(ch), cap(ch))
//新建协程
go func() {
for i := 0; i < 10; i++ {
ch <- i //往chan写内容
fmt.Printf("子协程[%d]:len(ch) = %d,cap(ch) = %d\n", i, len(ch), cap(ch))
}
}()
//延时
time.Sleep(2 * time.Second)
for i := 0; i < 10; i++ {
num := <-ch //读管道中内容,没有内容前,阻塞
fmt.Println("num = ", num)
}
}
#结果
len(ch) = 0 , cap(ch) = 3
子协程[0]:len(ch) = 1,cap(ch) = 3
子协程[1]:len(ch) = 2,cap(ch) = 3
子协程[2]:len(ch) = 3,cap(ch) = 3
num = 0
num = 1
num = 2
num = 3
子协程[3]:len(ch) = 3,cap(ch) = 3
num = 4
子协程[4]:len(ch) = 0,cap(ch) = 3
子协程[5]:len(ch) = 0,cap(ch) = 3
num = 5
num = 6
子协程[6]:len(ch) = 1,cap(ch) = 3
子协程[7]:len(ch) = 0,cap(ch) = 3
子协程[8]:len(ch) = 1,cap(ch) = 3
子协程[9]:len(ch) = 2,cap(ch) = 3
num = 7
num = 8
num = 9
网友评论