我试图在下面重现一种情况,其中我试图同时运行三个函数。但是,我只能在第一个函数的某个点之后运行第二个和第三个函数,因为它取决于第一个函数的值。对于这种情况,我使用了一个 channel 。这是我的代码:
package code
import "fmt"
func First(c chan string) {
for i := 0; i < 10000; i++ {
continue
}
test := "test"
fmt.Println(test)
c <- test
for i := 0; i < 10000; i++ {
fmt.Print(i)
}
}
func Second(c chan string) {
msg:= <- c
fmt.Println(msg)
if msg != "" { // I need to run the whole of First before running second and third concurrently then
fmt.Println("second", msg)
for i := 0; i < 10000; i++ {
fmt.Print(i)
}
}
}
func Third(c chan string) {
msg:= <- c
fmt.Println("third", msg)
for i := 0; i < 10000; i++ {
fmt.Print(i)
}
}
package main
import (
"./code"
"fmt"
"sync"
//"sync"
"time"
)
func main() {
start := time.Now()
var wg sync.WaitGroup
wg.Add(3)
var c chan string = make(chan string)
go func() {
code.First(c)
wg.Done()
}()
go func() {
code.Second(c)
wg.Done()
}()
go func() {
code.Third(c)
wg.Done()
}()
wg.Wait()
end := time.Now()
delta := end.Sub(start)
fmt.Println("time", delta.Seconds())
}
目前,我陷入了僵局。几个额外的问题——有没有办法首先检查 channel 给出的值,如果它们不是某些预期值,我首先完成第一个函数的运行,然后同时运行第二个和第三个?本质上是一张像我第二次添加的支票?如果它是预期值,我希望所有函数在 channel 从第一个函数获取特定值后同时运行。
最佳答案
您的主程序生成三个额外的 goroutine,然后等待所有三个 goroutine 发出信号(通过 wg.Done
)它们已完成。所有三个 goroutine,加上 main
本身,共享一个 channel ,您可以通过该 channel 一次发送一个 string
实例(并且您可以使用它只发送一个)。
一个 goroutine(它调用 code.First
)旋转一会然后发送一个字符串。发送字符串后,该 goroutine 会打印许多数字,然后发出完成并退出的信号。
另外两个 goroutine(调用 code.Second
和 code.Third
)立即阻塞等待接收字符串。取决于它们运行的确切时间以及谁获得字符串的变幻莫测,它们中的一个 将获得 code.First
发送的字符串。另一个仍然被阻止。
无论哪一个获得一个字符串(目前始终是 "test"
),然后那个会打印它的名字和许多数字,然后发出完成并退出的信号。
没有得到字符串的那个仍在等待字符串。同时,main
中的 wg.Wait
正在等待最后一个 wg.Done
调用,由于所有剩余的 goroutines 都在等待,因此不会再发生(现在只有这两个 — main
和 没有 得到字符串的那个 — 左边)。这是你的僵局。
看起来好像您希望两个 goroutines 接收从code.First
发送的字符串。这不会发生:其中一个获得字符串,另一个继续等待。 (没有关于谁得到字符串的 promise 。)
A couple extra questions- is there a way to first check the values given by the channel ...
当然:无论你得到什么字符串,你都有一个字符串。你可以用它做任何你喜欢的操作,就像你已经将它与 ""
进行比较一样。
... and if they are not certain expected values I first complete running the first function and then run second and third concurrently
这只是编程的一个小问题。但是,如果您希望能够控制谁 获取哪些 消息,则每个接收goroutine 需要一个 channel 。如果你创建两个单独的 channel ,code.First
可以同时使用这两个 channel ,并且可以在你喜欢的任何时候向任何一个额外的 goroutine 发送适当的消息。
关于go - 为什么我会出现死锁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57898354/