23

go语言 make(chan int, 1) 和 make (chan int) 的区别

 4 years ago
source link: https://studygolang.com/articles/26149
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

遇到golang channel 的一个问题:发现go 协程读取channel 数据 并没有按照预期进行协作执行。

经过查资料:

使用channel 操作不当导致,channel分 有缓冲区无缓冲区 , 以下是两者的区别。

无缓冲区channel

用make(chan int) 创建的chan, 是无缓冲区的, send 数据到chan 时,在没有协程取出数据的情况下, 会阻塞当前协程的运行。ch <- 后面的代码就不会再运行,直到channel 的数据被接收,当前协程才会继续往下执行。

ch := make(chan int)  // 创建无缓冲channel

go func() {
    fmt.Println("time sleep 5 second...")
    time.Sleep(5 * time.Second)
    <-ch
}()
h
fmt.Println("即将阻塞...")
ch <-1   // 协程将会阻塞,等待数据被读取
fmt.Println("ch 数据被消费,主协程退出")

有缓冲区channel

channel 的缓冲区为1,向channel 发送第一个数据,主协程不会退出。发送第二个时候,缓冲区已经满了, 此时阻塞主协程。

ch := make(chan int, 1)  // 创建有缓冲channel

go func() {
    fmt.Println("time sleep 5 second...")
    time.Sleep(5 * time.Second)
    <-ch
}()

ch <-1   // 协程不会阻塞,等待数据被读取

fmt.Println("第二次发送数据到channel, 即将阻塞")
ch <-1   // 第二次发送数据到channel, 在数据没有被读取之前,因为缓冲区满了, 所以会阻塞主协程。

fmt.Println("ch 数据被消费,主协程退出")

总结: 在创建channel的时候, 要注意是否需要缓冲区。有缓冲区时:在不超过缓冲区大小时,不会出现 发送方阻塞. 无缓冲区时: 只要channel 数据没有被拿走,始终会阻塞发送方。

感谢这位大神的文章: https://studygolang.com/artic...


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK