在并发编程中,通道(channel)和goroutine是Go语言的重要特性。它们可以帮助我们高效地实现并发操作。本篇博客将介绍在单一接收方与多个发送方的场景中,如何优雅地关闭通道。
示例代码
我们使用一个例子来演示多个发送方goroutine和一个接收方goroutine的工作机制:
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
rand.Seed(time.Now().UnixNano())
const Max = 100000
const NumSenders = 1000
dataCh := make(chan int, 100)
stopCh := make(chan struct{})
doneCh := make(chan struct{})
// senders
for i := 0; i < NumSenders; i++ {
go func() {
for {
select {
case <-stopCh:
return
case dataCh <- rand.Intn(Max):
}
}
}()
}
// receiver
go func() {
for value := range dataCh {
if value == Max-1 {
fmt.Println("send stop signal to senders.")
close(stopCh)
close(doneCh)
return
}
fmt.Println(value)
}
}()
// Wait for receiver to signal completion
select {
case <-doneCh:
case <-time.After(time.Hour):
}
}
代码解析
-
多个发送方(发送goroutine):
- 有1000个发送方goroutine,每个goroutine都会不断生成随机数并尝试发送到
dataCh
通道。 - 当
dataCh
已满(即通道中有100个未被接收的值),所有发送方goroutine都会在尝试发送时阻塞,直到通道中有空位。
- 有1000个发送方goroutine,每个goroutine都会不断生成随机数并尝试发送到
-
单一接收方(接收goroutine):
- 有一个接收方goroutine,它会不断从
dataCh
通道中接收数据。 - 当接收方从通道中接收数据时,通道中的一个空位会被释放,使得一个阻塞的发送方可以继续发送数据。
- 接收方检查接收到的数据是否等于
Max-1
。如果是,它会打印信息并关闭stopCh
,通知所有发送方goroutine停止发送。
- 有一个接收方goroutine,它会不断从
结论
- 这是一个典型的单一接收方与多个发送方的并发模式。