jjzjj

go - fatal error : goroutines are asleep - deadlock

coder 2023-07-01 原文

努力学习并发。我遇到了以下错误:

fatal error: all goroutines are asleep - deadlock!

我被告知要添加一个 WaitGroup 和一个关闭 channel 来解决这个问题。我已经添加了这两个,但错误仍然存​​在。不确定我做错了什么。

这是我的代码 https://play.golang.org/p/ZB45oXlBUl :

package main

import (
    "log"
    "sync"
    "time"
)

type RowInfo struct {
    id int64
}

func main() {
    queueChan := make(chan RowInfo)
    workerChan := make(chan RowInfo)
    doneChan := make(chan int64)
    closeChan := make(chan struct{})

    var waitGroup sync.WaitGroup

    go dispatcher(queueChan, workerChan, doneChan, closeChan)

    // Start WorkerCount number of workers
    workerCount := 4
    for i := 0; i < workerCount; i++ {
        go worker(workerChan, doneChan, &waitGroup)
    }

    // Send test data
    waitGroup.Add(12)
    for i := 0; i < 12; i++ {
        queueChan <- RowInfo{id: int64(i)}
    }

    // Prevent app close till finished execution
    waitGroup.Wait()

    close(closeChan)
}

func dispatcher(queueChan, workerChan chan RowInfo, doneChan chan int64, closeChan chan struct{}) {
    state := make(map[int64]bool)

    for {
        select {
        case job := <-queueChan:
            if state[job.id] == true {
                continue
            }
            workerChan <- job
        case result := <-doneChan:
            state[result] = false
        case <-closeChan:
            close(queueChan)
            close(workerChan)
            close(doneChan)
            break
        }
    }
}

func worker(workerChan chan RowInfo, doneChan chan int64, waitGroup *sync.WaitGroup) {
    for job := range workerChan {
        time.Sleep(1 * time.Second)
        log.Printf("Doing work on job rowInfo ID: %d", job.id)

        // Finish job
        doneChan <- job.id
        waitGroup.Done()
    }
}

错误:

2009/11/10 23:00:01 Doing work on job rowInfo ID: 2
2009/11/10 23:00:01 Doing work on job rowInfo ID: 0
2009/11/10 23:00:01 Doing work on job rowInfo ID: 3
2009/11/10 23:00:01 Doing work on job rowInfo ID: 1
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /tmp/sandbox490337982/main.go:32 +0x1e0

goroutine 5 [chan send]:
main.dispatcher(0x104360c0, 0x10436100, 0x10436140, 0x10436180)
    /tmp/sandbox490337982/main.go:50 +0x200
created by main.main
    /tmp/sandbox490337982/main.go:21 +0x100

goroutine 6 [chan send]:
main.worker(0x10436100, 0x10436140, 0x104382e0, 0x0)
    /tmp/sandbox490337982/main.go:68 +0x1a0
created by main.main
    /tmp/sandbox490337982/main.go:26 +0x160

goroutine 7 [chan send]:
main.worker(0x10436100, 0x10436140, 0x104382e0, 0x0)
    /tmp/sandbox490337982/main.go:68 +0x1a0
created by main.main
    /tmp/sandbox490337982/main.go:26 +0x160

goroutine 8 [chan send]:
main.worker(0x10436100, 0x10436140, 0x104382e0, 0x0)
    /tmp/sandbox490337982/main.go:68 +0x1a0
created by main.main
    /tmp/sandbox490337982/main.go:26 +0x160

goroutine 9 [chan send]:
main.worker(0x10436100, 0x10436140, 0x104382e0, 0x0)
    /tmp/sandbox490337982/main.go:68 +0x1a0
created by main.main
    /tmp/sandbox490337982/main.go:26 +0x160

最佳答案

为了理解这个问题,想想 dispatcherworkers 发生了什么。

  1. 初始状态:调度员和 worker 空闲
  2. 在 queueChan 上发送:dispatcher select 发送给 workerChan
  3. worker 读取 workerChan:休眠 4 秒,写入 doneChan。
  4. 2、3重复4次,直到所有 worker 都睡了
  5. 当所有工作人员都在 sleep 时,queueChan 上有另一个工作。
  6. 调度员去做那项工作
  7. 调度程序无法在 workerChan 上发送,因为没有工作人员正在读取。
  8. 所有工作人员都熬过 sleep 并尝试发送 doneChan。

现在所有的 goroutines 都被阻塞了。

关于go - fatal error : goroutines are asleep - deadlock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35351751/

有关go - fatal error : goroutines are asleep - deadlock的更多相关文章

  1. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  2. ruby-on-rails - 用于 Ruby 的 vim 中的全局 "Go to definition"? - 2

    自97年以来我一直在使用vi/vim进行各种快速编辑和管理任务,但最近才考虑使用它来替换Netbeans作为我选择的ruby​​编辑器。我发现一件事在Netbeans和Eclipse中非常有用的是Ctrl+Click“转到定义”功能,您可以在其中按住Ctrl键并单击一个类或方法,然后它将带您了解定义。现在,我玩过丰富的ctags和rails.vim,而且很接近,但没有雪茄。这就是我想要的:默认情况下在Netbeans和Eclipse中,您可以在本地rails中按住ctrl并单击本地方法或类项目,但你也可以ctrl+click定义在gems或用Ruby编写的系统库。以Netbeans为例

  3. ruby-on-rails - Rails 上的 ruby : How to have multiple submit buttons going to different methods (maybe with with_action? ) - 2

    这个问题在这里已经有了答案:HowdoIcreatemultiplesubmitbuttonsforthesameforminRails?(7个答案)关闭9年前。所以..'save'%>'library'%>然后在我的Controller中:with_actiondo|a|a.savedoenda.librarydoendend问题是只有一个操作被调用...两个submit_tags调用相同的操作...知道为什么吗?或者我如何获得两个按钮以将表单提交给两种不同的方法?

  4. DiFi: A Go-as-You-Pay Wi-Fi Access System 精读笔记(三) - 2

    IV.SYSTEMIMPLEMENTATIONWeadoptmodulardesignfollowingtheintegrationofblockchain.Itbringsmoreflexibilitybyseparatingtheimplementationofdifferentfunctionalities,sowecouldleveragetheadvantagesoftheblockchain-basedsmartcontractwhilereducingoverhead.Figure3illustrateshowdifferentmodulesareinvolvedintheint

  5. go-templates - 如何根据表达式有条件地在 Go 模板中设置变量,如果不使用 if 语句包装可能会导致错误 - 2

    问题我该如何做这样的事情:{{$use_ssl:=(ne$.Env.CERT_NAME"")}}其中$.Env.CERT_NAME可能为零/未定义。如果它是零,它给出这个错误:at:errorcallingne:invalidtypeforcomparison注意:我无法控制传递给Go模板的对象,因此必须完全在模板本身内解决这个问题。我尝试过的我试图通过首先检查它是否为非空来变通:{{$use_ssl:=(($.Env.CERT_NAME)&&(ne$.Env.CERT_NAME""))}}但它给出了这个错误:unexpected"&"inoperand所以我切换到这个,这在语法上是允

  6. Go time与string的相爱相杀 - 2

    time包与string包可以说是在Go语言的开发中常用的两个包实际开发过程中(例如web开发)经常会遇到time类型与string类型的交互,计算比较等场景首先来了解GO语言里非常浪漫的一个点,即2006-01-0215:04:05,GO语言诞生的时间,通常用来做时间的格式化time转stringt:=time.Now()//当前时间timeLayoutStr:="2006-01-0215:04:05"t.Format(timeLayoutStr)//返回值为string,可以用一个值来接收它上述例子中,将time类型t转换为string类型,并格式化为年-月-日时-分-秒,这里的格式化是可

  7. javascript - 使用哈希 url 卡在 Angular ui-router State.go 上? - 2

    我正在研究ui-router。我有一个状态:.state('new-personal-orders',{url:'/orders/new-personal-orders/:catId?',template:''})在我的Controller中,我可以使用$state.go('new-personal-orders',null,{reload:true})在Html文件中我有一个anchor标记:Link如果标签被点击,状态就会改变,'new-personal-orders'变成当前状态,在url中有尾随散列。然后url看起来像:http://localhost:3000/orders/

  8. 十分钟 Javascript : What is going on in this example code illustrating lazy scoping? - 2

    我一直在重读SpencerTipping的优秀作品JavascriptinTenMinutes在这个使用惰性作用域创建语法宏的示例中,我终究无法弄清楚发生了什么:varf=function(){return$0+$1};varg=eval(f.toString().replace(/\$(\d+)/g,function(_,digits){return'arguments['+digits+']'}));g(5,6);//=>11(exceptonIE)特别是,$0和$1正在被一个函数定义取代——那个函数是如何被计算的?(大概是通过eval(),但我没有看到)。函数中单个下划线参数的用

  9. javascript - 如何用参数做 $state.go() ? - 2

    我已经完美地初始化了$stateProvider并且我正在将所有这些状态与ui-sref一起使用。效果很好。用户按下按钮并通过$stateProvider进入编辑页面。在这个页面上,我有一个执行$http请求的表单:this.pushData=function(data){$http.post('/data/'+$stateParams.dataId+'/otherdata',JSON.stringify({id:otherdata.id,name:otherdata.name}),configAuth).then(functionsuccess(response){varaddedD

  10. Go第 15 章 :单元测试 - 2

    Go第15章:单元测试15.1先看一个需求在我们工作中,我们会遇到这样的情况,就是去确认一个函数,或者一个模块的结果是否正确,如:15.2传统的方法15.2.1传统的方式来进行测试在main函数中,调用addUpper函数,看看实际输出的结果是否和预期的结果一致,如果一致,则说明函数正确,否则函数有错误,然后修改错误代码实现:15.2.2传统方法的缺点分析不方便,我们需要在main函数中去调用,这样就需要去修改main函数,如果现在项目正在运行,就可能去停止项目。不利于管理,因为当我们测试多个函数或者多个模块时,都需要写在main函数,不利于我们管理和清晰我们思路引出单元测试。->testin

随机推荐