无缓冲的channel
channel
的默认类型就是无缓冲的。当一个数据被发送到无缓冲的channel
中,发送操作会被阻塞,知道有另一个goroutine
从这个channel
中接收这个数据。同样,当试图从一个无缓冲的channel
中接收数据时,如果没有数据可以接收,接收操作也会被阻塞,直到有另一个goroutine
发送数据到这个channel
。因此,无缓冲的channel
提高了一种强同步的通信机制,发送和接收操作在完成数据交换的时候都会阻塞,确保了数据在不同的goroutine
之间精确同步。
有缓冲的channel
有缓冲的channel
具有一个固定大小的缓冲区。当数据被发送到有缓冲的channel
时,如果缓冲区未满,发送操作就会立刻返回,否则发送操作会阻塞,直到有另一个goroutine
从channel
中接收数据病空出空间。当从一个有缓冲的channel
接收数据的时候,如果缓冲区有数据,接收操作会被立刻返回,否则接收操作会阻塞,直到有另一个goroutine
发送数据到channel
。因此,有缓冲的channel
提供了一种弱同步的通信机制,发送和接收操作可能不会阻塞,是的goroutine
可以继续执行其他的操作。
使用场景
- 无缓冲的
channel
适用于确保两个goroutine
必须同步进行的场景,比如确保某个事件发生后才进行下一步操作。 - 有缓冲的
channel
适用于想要减少因等待而导致的阻塞的场景,或者当数据生产速度不定时,缓冲可以帮助平滑数据流动和处理。
以下是一个使用示例,无缓冲的情况下,发送操作会阻塞,因此打印操作也无法执行,直到接收操作完成;而有缓冲的情况下,发送操作不会阻塞,所以会继续向下执行打印操作。
package main
import (
"fmt"
"time"
)
func main() {
// 无缓冲的channel
unbuffered := make(chan string)
go func() {
unbuffered <- "Hello, World!"
fmt.Println("Sent message to unbuffered channel!")
}()
// 模拟处理延迟
time.Sleep(3 * time.Second)
fmt.Println(<-unbuffered)
// 有缓冲的channel
buffered := make(chan string, 1)
go func() {
buffered <- "Hello, World!"
fmt.Println("Sent message to buffered channel!")
}()
// 模拟处理延迟
time.Sleep(3 * time.Second)
fmt.Println(<-buffered)
}
最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB