jjzjj

go - throw 所有的 goroutines 都睡着了——僵局! ------- 谷歌GO的错误

coder 2024-07-12 原文

我想编写三个相互发送整数的并发 go 例程。现在,我的代码已正确编译,但在第一次执行后出现错误“抛出:所有 goroutines 都睡着了 - 死锁!”。我试图找到错误,但我无法在代码逻辑中找到任何错误。任何人都可以帮助我找到我的代码中的错误。我的代码如下。

package main

import "rand"

func Routine1(command12 chan int, response12 chan int, command13 chan int, response13 chan int) {

    // z12 is a variable which stores the value comming from channel 2 and z13 is a variable which stores the value comming from channel 3.

    z12 := 200
    z13 := 200
    m12 := false
    m13 := false
    y := 0

    for i := 0; i < 20; i++ {
        y = rand.Intn(100)

        // If y's value is not 0 then the value will be sent to routine 2 or 3 according to   prime or not.
        // If y's value is 0 then process state (the varibles used by it means z12, z13) and channel state will be saved.[routine 1 is initiator]

        if y == 0 {
            print(z12, "    z12 STATE SAVED\n")
            print(z13, "    z13 STATE SAVED\n")

            // Routine 1 is initiator,  it sends 0 to make other process to save the state.

            y = 0
            command12 <- y
            command13 <- y

            // Untill routine 2 and 3 does not send 0, process 1 is on channel saving state (it's process state is already saved).
            // When routine 1 recives 0 from both other processes, channel is saved and routine 1 retuns to it's common routine procedure.
            // When routine 1 recives 0 from any other processes, saving channel bettwen them is stopped.
            // m12, m13 is used to mark whether 0 recived or not.

            for m12 != true || m13 != true {
                select {
                case cmd1 := <-response12:
                    {
                        z12 = cmd1
                        if z12 != 0 {
                            print(z12, "    z12  Channel Saving.... \n")
                            y = rand.Intn(100)
                            command12 <- y
                        }
                        if z12 == 0 {
                            m12 = true
                            print(" z12  Channel Saving Stopped \n")
                        }
                    }

                case cmd2 := <-response13:
                    {
                        z13 = cmd2
                        if z13 != 0 {
                            print(z13, "    z13  Channel Saving.... \n")
                            y = rand.Intn(100)
                            command13 <- y
                        }
                        if z13 == 0 {
                            m13 = true
                            print("    z13  Channel Saving Stopped \n")
                        }
                    }
                }

            }

            // After saving process state it retuns to it's normal behaviour.

            m12 = false
            m13 = false
        }

        if y != 0 {

            // If y value is not 0, routine 1 just sends int to other process according to prime or not and recives int accordingly.

            if y%2 == 0 {
                command12 <- y
            }

            if y%2 != 0 {
                command13 <- y
            }
            select {
            case cmd1 := <-response12:
                {
                    z12 = cmd1
                    print(z12, "    z12\n")
                }
            case cmd2 := <-response13:
                {
                    z13 = cmd2
                    print(z13, "   z13\n")
                }
            }
        }
    }
    close(command12)
    close(command13)
}


//Routine 2 (or 3) is not an initiator (means it can't send 0). When it recives 0 (from routine 1 or 3) it save the state of process and the state of the channel from which it recived).
// When it recives 0 from both other two routine, it saves all channel state and returns to it's common behaviour. [same in routine 3]

func Routine2(command12 chan int, response12 chan int, command23 chan int, response23 chan int) {
    z21 := 200
    z23 := 200
    m21 := false
    m23 := false

    for i := 0; i < 20; i++ {
        select {
        case x, open := <-command12:
            {
                if !open {
                    return
                }
                if x != 0 && m23 != true {
                    z21 = x
                    print(z21, "   z21\n")
                }
                if x != 0 && m23 == true {
                    z21 = x
                    print(z21, "   z21 Channel Saving \n")
                }
                if x == 0 {
                    m21 = true
                    if m21 == true && m23 == true {
                        print(" z21 and z23 Channel Saving Stopped \n")
                        m23 = false
                        m21 = false
                    }
                    if m21 == true && m23 != true {
                        z21 = x
                        print(z21, "   z21  Channel Saved \n")

                    }

                }
            }

        case x, open := <-response23:
            {
                if !open {
                    return
                }
                if x != 0 && m21 != true {
                    z23 = x
                    print(z23, "   z21\n")
                }
                if x != 0 && m21 == true {
                    z23 = x
                    print(z23, "   z23 Channel Saving \n")
                }
                if x == 0 {
                    m23 = true
                    if m21 == true && m23 == true {
                        print(" z23 Channel Saving Stopped \n")
                        m23 = false
                        m21 = false
                    }
                    if m23 == true && m21 != true {
                        z23 = x
                        print(z23, "   z23  Channel Saved \n")
                    }

                }
            }
        }

        if m23 == false && m21 == false {
            y := rand.Intn(100)
            if y%2 == 0 {
                if y == 0 {
                    y = 10
                    response12 <- y
                }
            }

            if y%2 != 0 {
                if y == 0 {
                    y = 10
                    response23 <- y
                }
            }
        }

        if m23 == true && m21 != true {
            y := rand.Intn(100)
            response12 <- y
        }

        if m23 != true && m21 == true {
            y := rand.Intn(100)
            command23 <- y
        }

    }
    close(response12)
    close(command23)
}

func Routine3(command13 chan int, response13 chan int, command23 chan int, response23 chan int) {
    z31 := 200
    z32 := 200
    m31 := false
    m32 := false

    for i := 0; i < 20; i++ {
        select {
        case x, open := <-command13:
            {
                if !open {
                    return
                }
                if x != 0 && m32 != true {
                    z31 = x
                    print(z31, "   z21\n")
                }
                if x != 0 && m32 == true {
                    z31 = x
                    print(z31, "   z31 Channel Saving \n")
                }
                if x == 0 {
                    m31 = true
                    if m31 == true && m32 == true {
                        print(" z21 Channel Saving Stopped \n")
                        m31 = false
                        m32 = false
                    }
                    if m31 == true && m32 != true {
                        z31 = x
                        print(z31, "   z31  Channel Saved \n")

                    }

                }
            }

        case x, open := <-command23:
            {
                if !open {
                    return
                }
                if x != 0 && m31 != true {
                    z32 = x
                    print(z32, "   z32\n")
                }
                if x != 0 && m31 == true {
                    z32 = x
                    print(z32, "   z32 Channel Saving \n")
                }
                if x == 0 {
                    m32 = true
                    if m31 == true && m32 == true {
                        print(" z32 Channel Saving Stopped \n")
                        m31 = false
                        m32 = false
                    }
                    if m32 == true && m31 != true {
                        z32 = x
                        print(z32, "   z32  Channel Saved \n")

                    }

                }
            }
        }
        if m31 == false && m32 == false {
            y := rand.Intn(100)
            if y%2 == 0 {
                response13 <- y
            }

            if y%2 != 0 {
                response23 <- y
            }
        }

        if m31 == true && m32 != true {
            y := rand.Intn(100)
            response13 <- y
        }

        if m31 != true && m32 == true {
            y := rand.Intn(100)
            response23 <- y
        }

    }
    close(response13)
    close(response23)
}


func main() {

    // Three concurrent channels are created to pass integers to each other.
    // command 12 used to send int and response12 is used to receive int from routine 1 to routine 2.
    // response 12 used to send int and command 12 is used to receive int from routine 2 to routine 1. {so as for others}

    command12 := make(chan int)
    response12 := make(chan int)
    command13 := make(chan int)
    response13 := make(chan int)
    command23 := make(chan int)
    response23 := make(chan int)

    go Routine1(command12, response12, command13, response13)
    go Routine2(command12, response12, command23, response23)
    Routine3(command13, response13, command23, response23)
}

最佳答案

正如其他人所说 - 您的代码太复杂,我无法快速找出其预期逻辑。无论如何,“技术分析”方法带来了一些好处。当将 Gosched 作为默认情况添加到选择语句时 使 channel 缓冲 - 然后代码不再死锁。虽然我不知道它在做什么,也不知道它是否按照你想要的去做。

在我看来,从代码来看,行为是不确定的(?)。无论如何,我认为原始代码可能被设计破坏了(例如,一些循环看起来像是在忙着等待,即使它们运行了 N 次硬编码,原文如此!),很抱歉这么说。

“工作”(== 谁知道它在做什么)代码:http://play.golang.org/p/dcUpeJ9EUa

PS:第 325 行的缓冲区大小 const 不能低于 4(通过每周试运行)并且似乎提供了另一种改变代码行为的方法。

关于go - throw 所有的 goroutines 都睡着了——僵局! ------- 谷歌GO的错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8272760/

有关go - throw 所有的 goroutines 都睡着了——僵局! ------- 谷歌GO的错误的更多相关文章

  1. ruby - 如何以所有可能的方式将字符串拆分为长度最多为 3 的连续子字符串? - 2

    我试图获取一个长度在1到10之间的字符串,并输出将字符串分解为大小为1、2或3的连续子字符串的所有可能方式。例如:输入:123456将整数分割成单个字符,然后继续查找组合。该代码将返回以下所有数组。[1,2,3,4,5,6][12,3,4,5,6][1,23,4,5,6][1,2,34,5,6][1,2,3,45,6][1,2,3,4,56][12,34,5,6][12,3,45,6][12,3,4,56][1,23,45,6][1,2,34,56][1,23,4,56][12,34,56][123,4,5,6][1,234,5,6][1,2,345,6][1,2,3,456][123

  2. ruby-on-rails - 跳过状态机方法的所有验证 - 2

    当我的预订模型通过rake任务在状态机上转换时,我试图找出如何跳过对ActiveRecord对象的特定实例的验证。我想在reservation.close时跳过所有验证!叫做。希望调用reservation.close!(:validate=>false)之类的东西。仅供引用,我们正在使用https://github.com/pluginaweek/state_machine用于状态机。这是我的预订模型的示例。classReservation["requested","negotiating","approved"])}state_machine:initial=>'requested

  3. ruby - Nokogiri 剥离所有属性 - 2

    我有这个html标记:我想得到这个:我如何使用Nokogiri做到这一点? 最佳答案 require'nokogiri'doc=Nokogiri::HTML('')您可以通过xpath删除所有属性:doc.xpath('//@*').remove或者,如果您需要做一些更复杂的事情,有时使用以下方法遍历所有元素会更容易:doc.traversedo|node|node.keys.eachdo|attribute|node.deleteattributeendend 关于ruby-Nokog

  4. ruby - 获取模块中定义的所有常量的值 - 2

    我想获取模块中定义的所有常量的值:moduleLettersA='apple'.freezeB='boy'.freezeendconstants给了我常量的名字:Letters.constants(false)#=>[:A,:B]如何获取它们的值的数组,即["apple","boy"]? 最佳答案 为了做到这一点,请使用mapLetters.constants(false).map&Letters.method(:const_get)这将返回["a","b"]第二种方式:Letters.constants(false).map{|c

  5. ruby - 如何遍历 Ruby 中所有正则表达式匹配的字符串? - 2

    我们有一个字符串:“”这个正则表达式://i如何从当前字符串中获取所有匹配项? 最佳答案 "".scan(//)参见scan在ruby​​-docs上 关于ruby-如何遍历Ruby中所有正则表达式匹配的字符串?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/6857852/

  6. ruby-on-rails - 在所有延迟的作业之前 Hook - 2

    是否可以在所有delayed_job任务之前运行一个方法?基本上,我们试图确保每个运行delayed_job的服务器都有我们代码的最新实例,所以我们想运行一个方法来在每个作业运行之前检查它。(我们已经有了“check”方法并在别处使用它。问题只是关于如何从delayed_job中调用它。) 最佳答案 现在有一种官方方法可以通过插件来做到这一点。这篇博文通过示例清楚地描述了如何执行此操作http://www.salsify.com/blog/delayed-jobs-callbacks-and-hooks-in-rails(本文中描述

  7. ruby-on-rails - Ruby 流量控制 : throw an exception, 返回 nil 还是让它失败? - 2

    我在思考流量控制的最佳实践。我应该走哪条路?1)不要检查任何东西并让程序失败(更清晰的代码,自然的错误消息):defself.fetch(feed_id)feed=Feed.find(feed_id)feed.fetchend2)通过返回nil静默失败(但是,“CleanCode”说,你永远不应该返回null):defself.fetch(feed_id)returnunlessfeed_idfeed=Feed.find(feed_id)returnunlessfeedfeed.fetchend3)抛出异常(因为不按id查找feed是异常的):defself.fetch(feed_id

  8. ruby - 如何捕获 ruby​​ 中的所有异常? - 2

    我们如何捕获或/和处理ruby​​中所有未处理的异常?例如,这样做的动机可能是将某种异常记录到不同的文件或发送电子邮件给系统管理。在Java中我们会做Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandlerex);在Node.js中process.on('uncaughtException',function(error){/*code*/});在PHP中register_shutdown_function('errorHandler');functionerrorHandler(){$error=error_

  9. ruby - 递归地将所有数字字符串转换为 Ruby 哈希中的整数 - 2

    我有一个随机大小的散列,它可能有类似"100"的值,我想将其转换为整数。我知道我可以使用value.to_iifvalue.to_i.to_s==value来做到这一点,但我不确定我将如何在我的散列中递归地做到这一点,考虑到一个值可以是一个字符串,或一个数组(哈希或字符串),或另一个哈希。 最佳答案 这是一个非常简单的递归实现(尽管必须同时处理数组和散列会增加一些技巧)。deffixnumifyobjifobj.respond_to?:to_i#IfwecancastittoaFixnum,doit.obj.to_ielsifobj

  10. ruby - 如何将新的 rvm 安装与现有的 ruby​​ 版本相关联? - 2

    我遇到了RVM的问题,所以我卸载并重新安装了它。事实是我实际上尝试过rbenv,但这对我来说没有用,所以我试图让rvm重新启动并运行-而不必安装重复版本的Ruby。我至少安装了1个现有版本的Ruby:ruby--versionruby1.8.7(2011-12-28patchlevel357)[universal-darwin11.0]但是当我执行rvmlist时,我得到一个空白列表:bash-3.2$rvmlistrvmrubies#Defaultrubynotset.Try'rvmaliascreatedefault'.#=>-current#=*-current&&default

随机推荐