go - 为什么我会出现死锁?

标签 go concurrency goroutine

我试图在下面重现一种情况,其中我试图同时运行三个函数。但是,我只能在第一个函数的某个点之后运行第二个和第三个函数,因为它取决于第一个函数的值。对于这种情况,我使用了一个 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.Secondcode.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/

相关文章:

java - hawtdispatch : a simple threadpool example

go - 工作池的最佳大小

go - 如何理解以下代码中的 "ch=ch1"?

html - 通过 ParseForm() 检索表单选项 ID

golang 数组引用例如。 b[1 :4] references elements 1, 2,3

function - Golang 函数测试

linux - 在 linux 系统上从 golang 中的 xls 文件中读取值

c# - 使用静态变量的并发

java - Java 中使用信号量的循环线程

select - 选择中同时发生多个事件时的预期行为