从通道读取时未检测到“死锁”
Posted
技术标签:
【中文标题】从通道读取时未检测到“死锁”【英文标题】:Undetected "deadlock" while reading from channel 【发布时间】:2016-11-14 03:12:14 【问题描述】:从复杂程序的通道中读取不确定数量任务的执行结果时出现未检测到死锁的情况如何处理,例如:网络服务器?
package main
import (
"fmt"
"math/rand"
"time"
)
func main()
rand.Seed(time.Now().UTC().UnixNano())
results := make(chan int, 100)
// we can't know how many tasks there will be
for i := 0; i < rand.Intn(1<<8)+1<<8; i++
go func(i int)
time.Sleep(time.Second)
results <- i
(i)
// can't close channel here
// because it is still written in
//close(results)
// something else is going on other threads (think web server)
// therefore a deadlock won't be detected
go func()
for
time.Sleep(time.Second)
()
for j := range results
fmt.Println(j)
// we just stuck in here
如果程序更简单,请转到detects a deadlock and properly fails。大多数示例要么获取已知数量的结果,要么按顺序写入通道。
【问题讨论】:
这实际上不是一个死锁——你没有两个线程争用一个资源,你有一个线程在等待永远不会到来的数据。不涉及锁定。 在 go 错误消息中,一个非常相似的情况需要死锁:throw: all goroutines are asleep - deadlock!
;但我明白你的意思
【参考方案1】:
诀窍是使用sync.WaitGroup
并等待任务以非阻塞方式完成。
var wg sync.WaitGroup
// we can't know how many tasks there will be
for i := 0; i < rand.Intn(1<<8)+1<<8; i++
wg.Add(1)
go func(i int)
time.Sleep(time.Second)
results <- i
wg.Done()
(i)
// wait for all tasks to finish in other thread
go func()
wg.Wait()
close(results)
()
// execution continues here so you can print results
另请参阅:Go Concurrency Patterns: Pipelines and cancellation - The Go Blog
【讨论】:
以上是关于从通道读取时未检测到“死锁”的主要内容,如果未能解决你的问题,请参考以下文章