Golang中如何同时读写处理两个Channel
Golang中如何同时读写处理两个Channel 你好,
我正在尝试做一些事情来理解并解决类似“所有goroutine都处于休眠状态 - 死锁!”的问题。我使用了goroutine来进行读取和写入。那么为什么我还会遇到错误呢?
package main
func main() {
processData()
}
func processData() {
ch :=make(chan int , 10)
result :=make(chan int , 10)
for i:=0;i<10; i++{
go executeTask(ch, result)
}
for i:=0; i<100; i++{
ch <- i
}
for a:=0;a <10 ; a++{
<- result
}
println("test main")
}
func executeTask(ints chan int , result chan<- int) {
for r:= range ints{
result <- 1
println(r)
}
println("execute tasks")
}
更多关于Golang中如何同时读写处理两个Channel的实战教程也可以访问 https://www.itying.com/category-94-b0.html
因为你试图在读取任何响应之前发送100个项目。这100个项目需要存储在某个地方。
10个执行器goroutine读取10个项目,处理它们,并将结果写入结果缓冲区。结果缓冲区现在已经满了,因为你还没有开始读取它。
然后另外十个项目被处理,所有的执行器例程在发送结果时全部阻塞,因为结果通道已满。到目前为止,这是20个项目。
ch 通道随后缓冲了其中的10个。此时你已经发送了30个项目。
此时,没有任何进程可以继续——执行器无法发送结果,因为没有人读取结果;也无法发送新项目,因为执行器没有读取任何项目,所以系统陷入了死锁。
这是一个典型的死锁问题,原因是你的 executeTask goroutine 在 for r := range ints 循环中等待 ch 通道的数据,但 ch 通道从未被关闭,导致 goroutine 无法退出。同时,主 goroutine 在等待从 result 通道读取数据,但 executeTask 中的 result <- 1 可能因为 result 通道已满而阻塞。
以下是修改后的代码,通过关闭 ch 通道来通知 goroutine 停止接收,并确保所有 goroutine 都能完成:
package main
func main() {
processData()
}
func processData() {
ch := make(chan int, 10)
result := make(chan int, 10)
// 启动10个goroutine
for i := 0; i < 10; i++ {
go executeTask(ch, result)
}
// 发送100个数据到ch通道
for i := 0; i < 100; i++ {
ch <- i
}
// 关闭ch通道,通知goroutine停止接收
close(ch)
// 等待所有goroutine完成
for a := 0; a < 100; a++ {
<-result
}
println("test main")
}
func executeTask(ints chan int, result chan<- int) {
for r := range ints {
result <- 1
println(r)
}
println("execute tasks")
}
关键修改:
- 在发送完所有数据后调用
close(ch),这样for r := range ints循环会在通道关闭且数据读取完毕后自动退出 - 将
result的读取次数从10改为100,因为每个处理的任务都会发送一个结果
如果你想要更精确的控制,可以使用 sync.WaitGroup:
package main
import "sync"
func main() {
processData()
}
func processData() {
ch := make(chan int, 10)
result := make(chan int, 10)
var wg sync.WaitGroup
// 启动10个goroutine
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
executeTask(ch, result)
}()
}
// 发送100个数据到ch通道
for i := 0; i < 100; i++ {
ch <- i
}
// 关闭ch通道
close(ch)
// 等待所有goroutine完成
wg.Wait()
// 关闭result通道
close(result)
// 读取结果
for range result {
// 处理结果
}
println("test main")
}
func executeTask(ints chan int, result chan<- int) {
for r := range ints {
result <- 1
println(r)
}
println("execute tasks")
}
这个版本使用 sync.WaitGroup 来等待所有 worker goroutine 完成,然后安全地关闭 result 通道。

