使用单通道进行常规死锁
go routine deadlock with single channel
我最近开始学习围棋,但遇到了一个问题。
我有一个简单的 go 例程,它可以 returns 或将值推送到通道。
我的主要 fn 代表一直致力于此例程,直到它满足条件或数据耗尽。
此代码似乎在 "found" 频道上死锁。我做错了什么?
- 有多个工人
- 物品可以同时在多个工人身上找到
- 一旦找到项目,所有工人都应该停止。
.
func workerRoutine(data Data, found chan bool, wg *sync.WaitGroup){
defer (*wg).Done()
// data processing
// return on false
// multiple routines can set this at the same time
found <-true
}
func main {
// ....
found:=make(chan bool)
var wg sync.WaitGroup
itemFound:=false
Loop:
for i:=0; i<limit; i++ {
select {
case <-found:
itemFound = true
break Loop
default:
if(some_check) {
wg.Add(1)
go workerRoutine(mdata,found,&wg)
}
}
}
wg.Wait()
// use itemFound
}
一种可能的解决方案是避免使用 select 语句并为接收方(或发送方,或两者)使用单独的 goroutine。
示例:
package main
import "sync"
func worker(res chan bool, wg *sync.WaitGroup) {
res <- true
wg.Done()
}
func receiver(res chan bool, wg *sync.WaitGroup) {
for range res {
}
wg.Done()
}
func main() {
var wg, wg2 sync.WaitGroup
wg.Add(1)
wg2.Add(10)
found := make(chan bool)
go receiver(found, &wg)
for i := 0; i < 10; i++ {
go worker(found, &wg2)
}
wg2.Wait()
close(found)
wg.Done()
}
我最近开始学习围棋,但遇到了一个问题。 我有一个简单的 go 例程,它可以 returns 或将值推送到通道。 我的主要 fn 代表一直致力于此例程,直到它满足条件或数据耗尽。 此代码似乎在 "found" 频道上死锁。我做错了什么?
- 有多个工人
- 物品可以同时在多个工人身上找到
- 一旦找到项目,所有工人都应该停止。
.
func workerRoutine(data Data, found chan bool, wg *sync.WaitGroup){
defer (*wg).Done()
// data processing
// return on false
// multiple routines can set this at the same time
found <-true
}
func main {
// ....
found:=make(chan bool)
var wg sync.WaitGroup
itemFound:=false
Loop:
for i:=0; i<limit; i++ {
select {
case <-found:
itemFound = true
break Loop
default:
if(some_check) {
wg.Add(1)
go workerRoutine(mdata,found,&wg)
}
}
}
wg.Wait()
// use itemFound
}
一种可能的解决方案是避免使用 select 语句并为接收方(或发送方,或两者)使用单独的 goroutine。 示例:
package main
import "sync"
func worker(res chan bool, wg *sync.WaitGroup) {
res <- true
wg.Done()
}
func receiver(res chan bool, wg *sync.WaitGroup) {
for range res {
}
wg.Done()
}
func main() {
var wg, wg2 sync.WaitGroup
wg.Add(1)
wg2.Add(10)
found := make(chan bool)
go receiver(found, &wg)
for i := 0; i < 10; i++ {
go worker(found, &wg2)
}
wg2.Wait()
close(found)
wg.Done()
}