我正在尝试实施一个“工人”系统,但我遇到了一些问题,以确定其自身死锁的原因
通过调用fillQueue()
执行代码我不明白为什么我的代码最终出现在一个dealock中(正在进程正在等待“process()”的第二行,从通道“queue”读取,而另一个正在等待“fillQueue”结束时()“等待服务员阅读。
我不明白为什么它从未得到服务员的阅读。
func process(queue chan *entry, waiters chan bool) {
for {
entry, ok := <-queue
if ok == false {
break
}
fmt.Println("worker: " + entry.name)
entry.name = "whatever"
}
fmt.Println("worker finished")
waiters <- true
}
func fillQueue(q *myQueue) {
// fill our queue
queue := make(chan *entry, len(q.pool))
for _, entry := range q.pool {
fmt.Println("push entry")
queue <- entry
}
fmt.Printf("entry cap: %d\n", cap(queue))
// start the readers
var total_threads int
if q.maxConcurrent <= len(q.pool) {
total_threads = q.maxConcurrent
} else {
total_threads = len(q.pool)
}
waiters := make(chan bool, total_threads)
fmt.Printf("waiters cap: %d\n", cap(waiters))
var threads int
for threads = 0; threads < total_threads; threads++ {
fmt.Println("start worker")
go process(queue, waiters)
}
fmt.Printf("threads started: %d\n", threads)
for ; threads > 0; threads-- {
fmt.Println("wait for thread")
ok := <-waiters
fmt.Printf("received thread end: %b\n", ok)
}
}
这是运行时的日志:
push entry
push entry
push entry
entry cap: 3
waiters cap: 1
start worker
threads started: 1
wait for thread
worker: name1
worker: name2
worker: name3
throw: all goroutines are asleep - deadlock!
答案 0 :(得分:5)
简单回答:您需要关闭queue
。
如果频道关闭,双接收运算符将仅返回false,这是您永远不会做的。所以循环过程永远不会退出。顺便说一句,你可以用频道上的for / range替换你的for / if / break。
你应该考虑其他一些Go成语:你读过http://golang.org/doc/effective_go.html吗?