【问题标题】:Why do I have a deadlock?为什么我会出现死锁?
【发布时间】:2019-09-12 00:44:49
【问题描述】:

我试图在下面重新创建一个情况,其中我试图同时运行三个函数。但是,我只能在第一个函数的某个点之后运行第二个和第三个函数,因为它取决于第一个函数的值。对于这种情况,我使用了一个频道。这是我的代码:

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())
}

目前,我遇到了僵局。几个额外的问题 - 有没有办法首先检查通道给出的值,如果它们不是某些预期值,我首先完成运行第一个函数,然后同时运行第二个和第三个函数?本质上是一张像我第二次添加的支票?如果它是预期值,我希望所有函数在通道从第一个函数获取特定值后同时运行。

【问题讨论】:

    标签: go concurrency goroutine


    【解决方案1】:

    你的主程序产生了三个额外的 goroutine,然后等待三个都发出信号(通过wg.Done)它们已经完成。所有三个 goroutine 以及 main 本身共享一个通道,您可以通过该通道一次发送一个 string 实例(并且您可以使用该实例发送一个)。

    一个goroutine(调用code.First)旋转了一会儿,然后发送一个字符串。发送字符串后,该 goroutine 会打印许多数字,然后表示完成并退出。

    另外两个 goroutine(调用 code.Secondcode.Third)立即阻塞等待接收字符串。根据他们运行的确切时间以及获取字符串的人的变幻莫测,其中一个 将获得code.First 发送的字符串。另一个仍然被阻止。

    无论哪一个得到一个字符串(目前总是"test"),然后那个打印它的名字和许多数字,然后表示完成并退出。

    哪个没有得到一个字符串仍在等待一个字符串。同时,main 中的 wg.Wait 正在等待最后一个 wg.Done 调用,因为所有剩余的 goroutine 都在等待,所以不再发生这种情况(现在只有这两个 -main 和任何一个没有的 得到字符串——左)。这是你的僵局。

    您似乎希望 both 协程接收从code.First 发送的字符串。这不会发生:其中一个得到字符串,另一个继续等待。 (对于 获取字符串没有任何承诺。)

    几个额外的问题 - 有没有办法首先检查频道给出的值...

    当然:无论你得到什么字符串,你都有一个字符串。你可以用它做任何你喜欢的操作,就像你已经将它与""进行比较一样。

    ...如果它们不是某些预期值,我首先完成运行第一个函数,然后同时运行第二个和第三个函数

    这只是编程的小事。但是,如果您希望能够控制 接收哪些 消息,则每个接收goroutine 需要一个通道。如果你创建了两个独立的通道,code.First 可以同时使用这两个通道,并且可以在你喜欢的任何时候向任何一个额外的 goroutine 发送适当的消息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-06-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多