我对go例程有疑问。
我的代码:
func main() {
ok := make(chan bool, 1)
i := 0
fmt.Println("Starting...")
for i <= 3 {
fmt.Println("Loop: ", i)
go long(ok, i)
time.Sleep(1 * time.Second)
i = i + 1
select {
case _ = <-ok:
default:
fmt.Println("Default")
}
}
fmt.Println("Done...")
}
func long(c chan bool, i int){
fmt.Println("Inside long: ", i)
time.Sleep(3 * time.Second)
fmt.Println("Done with loop: ", i)
c <- true
}
这给了我输出:
Starting...
Loop: 0
Inside long: 0
Default
Loop: 1
Inside long: 1
Default
Loop: 2
Inside long: 2
Done with loop: 0
Loop: 3
Inside long: 3
Done with loop: 1
Done...
因为我使用了default
中的select
,所以该频道是非阻止的。主要功能退出,所有当前例程也退出。然后我阅读了sync
和WaitGrops
。
func main() {
ok := make(chan bool, 1)
var wg sync.WaitGroup
i := 0
fmt.Println("Starting...")
for i <= 3 {
fmt.Println("Loop: ", i)
wg.Add(1)
go long(ok, i)
time.Sleep(1 * time.Second)
i = i + 1
select {
case _ = <-ok:
default:
fmt.Println("Default")
}
}
wg.Wait()
fmt.Println("Done...")
}
这给了我:
Starting...
Loop: 0
Inside long: 0
Default
Loop: 1
Inside long: 1
Default
Loop: 2
Inside long: 2
Done with loop: 0
Loop: 3
Inside long: 3
Done with loop: 1
Done with loop: 2
Done with loop: 3
我们现在更接近我期望的执行,即: for循环使所有调用函数,然后我得到结果异步。如果一切顺利的话,这将是美好的。但是会产生错误:
fatal error: all goroutines are asleep - deadlock!
为什么会这样,我应该如何解决? (是否可以在不知道执行wg.Add()多少次的情况下进行修复?)
答案 0 :(得分:3)
您需要在def arrayCheck(nums):
for i in range(len(nums)-2):
if nums[i]==1 and nums[i+1]==2 and nums[i+3]==3:
return True
return False
x=arrayCheck([1, 1, 2, 3, 1])
print(x)
上致电Done()
,呼叫WaitGroup
,以便Add(1)
可以取消阻止。您不再需要频道同步:
wg.Wait()
答案 1 :(得分:1)
所以,比特&#39; answer会删除解决问题的渠道。
频道出现问题的原因是你的goroutines试图写入三次,缓冲区大小为1。并且您的主程序很快就会删除三个goroutine,并且由于select中的默认值而从不等待读取通道。因此它永远不会被读取,并且goroutines无法写入它。
答案 2 :(得分:0)
您也可以使用频道执行此操作,但它不如WaitGroup
那么优雅,因为它需要更多的同步工作。
对于上述问题,您可以执行以下操作:
package main
func main() {
ok := make(chan bool, 1)
done := make(chan bool)
i := 0
j := 0
fmt.Println("Starting...")
for i <= 3 {
fmt.Println("Loop: ", i)
go long(ok, i)
time.Sleep(1 * time.Second)
i = i + 1
}
go func() {
for {
select {
case _ = <-ok:
j++
if j == 4 {
done <- true
return
}
}
}
}()
<-done
fmt.Println("Done...")
}
func long(c chan bool, i int) {
fmt.Println("Inside long: ", i)
time.Sleep(3 * time.Second)
fmt.Println("Done with loop: ", i)
c <- true
}