当前位置: 首页 > 知识库问答 >
问题:

致命错误:所有goroutines都处于Hibernate状态-死锁

严易安
2023-03-14
package main

import (
    "fmt"
    "math/rand"
)

const (
    ROCK int = iota
    PAPER
    SCISSORS
)

type Choice struct {
    Who   int //0 you 1 your opponent
    Guess int
}

//Win returns true if you win.
func Win(you, he int) bool {
    ...
}

func Opponent(guess chan Choice, please chan struct{}) {
    for i := 0; i < 3; i++ {
        <-please
        choice := rand.Intn(3)
        who := 1
        guess <- Choice{who, choice}
        please <- struct{}{}
    }
}

func GetChoice(you, he int) int {
    ...
}

var Cheat func(guess chan Choice) chan Choice = func(guess chan Choice) chan Choice {
    new_guess := make(chan Choice)
    // go func() {
    for i := 0; i < 3; i++ {
        g1 := <-guess
        g2 := <-guess
        if g1.Who == 0 {
            choice := GetChoice(g1.Guess, g2.Guess)
            new_guess <- g2
            new_guess <- Choice{g1.Who, choice}
        } else {
            choice := GetChoice(g2.Guess, g1.Guess)
            new_guess <- g1
            new_guess <- Choice{g2.Who, choice}
        }
    }
    // }()
    fmt.Println("...")
    return new_guess
}

func Me(guess chan Choice, please chan struct{}) {

    for i := 0; i < 3; i++ {
        <-please
        choice := rand.Intn(3)
        who := 0
        guess <- Choice{who, choice}
        please <- struct{}{}
    }
}

func Game() []bool {
    guess := make(chan Choice)
    //please sync 2 goroutines.
    please := make(chan struct{})
    go func() { please <- struct{}{} }()
    go Opponent(guess, please)
    go Me(guess, please)
    guess = Cheat(guess)
    var wins []bool

    for i := 0; i < 3; i++ {
        g1 := <-guess
        g2 := <-guess
        win := false
        if g1.Who == 0 {
            win = Win(g1.Guess, g2.Guess)
        } else {
            win = Win(g2.Guess, g1.Guess)
        }
        wins = append(wins, win)
    }

    return wins
}

func main() {
    win := Game()
    fmt.Println(win)
}

共有1个答案

曾涵育
2023-03-14

在这个简化的示例中:

func Cheat(guess chan Choice) chan Choice {
        new_guess := make(chan Choice)
        new_guess <- Choice{}
        <-guess
        return new_guess
}

当对新分配的通道进行写操作时,没有其他人可能还拥有该通道,因此写操作将永远阻塞。由于写块,从guess读取就不会发生。但是,在您引用的代码中,cheak()函数是从gues通道读取的唯一内容;因此,写到它的内容在读发生时被阻止,在写到new_guess发生之前,读不会发生,在包含函数返回之前,写不会发生。

如果您将通道I/O移到goroutine,那么包含函数可以在事情进展之前返回,因此在cheak()中的write与game()末尾的reads配对,事情可以向前推进。

 类似资料:
  • 问题内容: 下面的代码与硬编码的JSON数据一起正常工作,但是当我从文件中读取JSON数据时不起作用。我得到使用时的错误。 硬编码JSON数据的工作示例: 输出: 不起作用-读取JSON数据文件的示例: 输出值 主机 问题答案: 当主功能结束时,Go程序结束。 从语言规范 程序执行首先初始化主程序包,然后调用函数main。当该函数调用返回时,程序退出。它不等待其他(非主)goroutine完成。

  • 问题内容: 我正在尝试剥离一组goroutine,然后等待它们全部完成。 但是,当我运行此代码时,出现以下错误: 我很困惑,因为我写的几乎与文档示例所演示的完全一样。 问题答案: 您需要将指针传递给WaitGroup,而不是WaitGroup对象。当您传递实际的WaitGroup时,Go会生成该值的副本,然后调用该副本。结果是原始的WaitGroup将具有10个Add,而没有Done,并且Wait

  • 问题内容: 我想编写三个同时发送整数的并发go例程。现在,我的代码已正确编译,但是在第一次执行后,出现错误“所有goroutine都处于睡眠状态- 死锁!”。我试图找到错误,但是在代码逻辑中找不到任何错误。有人可以帮助我在我的代码中查找错误。我的代码如下。提前致谢。 谁能告诉我为什么我将Routine2和Routine3声明为go例程,为什么输出为[no output]。我是GO语言的新手,据我从

  • 再次,我很困惑...我相信我的问题有一个简单的答案。 我的问题是;我如何告诉Hibernate MySQL包含中值函数,而不是返回错误? [IllegalStateException:没有节点的数据类型:org.hibernate.hql.internal.ast.tree.MethodNode-[METHOD_CALL]MethodNode:'('-[METHOD_NAME]IdentNode:

  • 问题内容: 作为升级JRun的一部分,我们正在从1.4 JVM迁移到1.6 JVM。现在,我收到一个非常奇怪的oracle db错误:“ OALL8处于不一致状态”。我已经解决了插入根本不使用绑定变量的查询的问题- 所有内联参数。如果我在没有任何绑定变量的情况下运行查询,则会收到上述错误。一旦我用绑定变量替换了一个硬编码值,一切都会正常工作。 另一个奇怪的地方是,在执行查询之后,它实际上已提交给数

  • 科尔多瓦应用程序在将手机升级到Android 9后停止工作 这是发送请求的代码 当手机连接到wifi时,一切都正常工作,当通过手机切换到数据时,应用程序停止工作。我连接了调试器,所有GET请求都处于状态(挂起)。 我已经在REST客户端应用程序中测试了通过蜂窝连接访问API的能力,它工作正常。 科尔多瓦网络应用程序可以很好地处理这部手机上的蜂窝数据。 Android 9中有什么变化会导致这种行为?