首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >所有围棋程序都处于休眠死锁状态

所有围棋程序都处于休眠死锁状态
EN

Stack Overflow用户
提问于 2016-02-11 16:19:10
回答 1查看 86关注 0票数 0

我正在学习如何做并发,我已经将其编写为自己的应用程序,这样一旦它工作起来,我就可以将它移植到不同的项目中。

我要添加它的项目基本上会向全局QueueChannel发送一个RowInfo,然后我的工作人员就应该开始处理这项工作了。如果我使用相同的ID对两行进行排队,并且其中一行当前正在由工作程序处理,那么我将从队列中删除重复的行(正如您可以看到我在dispatcher中执行"continue“的位置)。

这个队列/工作者代码将在ListenAndServe上阻塞的web服务器上运行,所以我希望它始终保持运行状态,并且工作者始终保持主动寻找作业。我不想关闭频道(除非我按下ctrl+C组合键打开了应用程序或其他东西)。我怀疑我得到的错误与没有关闭通道有关,因为这是许多提到这个错误的其他线程似乎表明的,但我不确定它与我拥有的代码到底有什么关系。

终端错误输出:

代码语言:javascript
运行
复制
[~/go/src/github.com/zzz/asynch]> go run main.go
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()
    /home/zzz/go/src/github.com/zzz/asynch/main.go:29 +0x14b

goroutine 5 [select]:
main.diszzzcher(0xc82001a120, 0xc82001a180, 0xc82001a1e0)
    /home/zzz/go/src/github.com/zzz/asynch/main.go:42 +0x21a
created by main.main
    /home/zzz/go/src/github.com/zzz/asynch/main.go:19 +0xb1

goroutine 6 [chan receive]:
main.worker(0xc82001a180, 0xc82001a1e0)
    /home/zzz/go/src/github.com/zzz/asynch/main.go:55 +0x54
created by main.main
    /home/zzz/go/src/github.com/zzz/asynch/main.go:24 +0xf7

goroutine 7 [chan receive]:
main.worker(0xc82001a180, 0xc82001a1e0)
    /home/zzz/go/src/github.com/zzz/asynch/main.go:55 +0x54
created by main.main
    /home/zzz/go/src/github.com/zzz/asynch/main.go:24 +0xf7

goroutine 8 [chan receive]:
main.worker(0xc82001a180, 0xc82001a1e0)
    /home/zzz/go/src/github.com/zzz/asynch/main.go:55 +0x54
created by main.main
    /home/zzz/go/src/github.com/zzz/asynch/main.go:24 +0xf7

goroutine 9 [chan receive]:
main.worker(0xc82001a180, 0xc82001a1e0)
    /home/zzz/go/src/github.com/zzz/asynch/main.go:55 +0x54
created by main.main
    /home/zzz/go/src/github.com/zzz/asynch/main.go:24 +0xf7
exit status 2

代码:

代码语言:javascript
运行
复制
package main

import (
    "log"
    "time"
)

type RowInfo struct {
    id int64
}

var QueueChan chan RowInfo

func main() {
    QueueChan := make(chan RowInfo)
    workerChan := make(chan RowInfo)
    exitChan := make(chan int64)

    go dispatcher(QueueChan, workerChan, exitChan)

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

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

    // Prevent app close
    for {
        time.Sleep(1 * time.Second)
    }
}

func dispatcher(queueChan, workerChan chan RowInfo, exitChan chan int64) {
    state := make(map[int64]bool)

    for {
        select {
        case job := <-QueueChan:
            if state[job.id] == true {
                continue
            }
            workerChan <- job
        case result := <-exitChan:
            state[result] = false
        }
    }
}

func worker(workerChan chan RowInfo, exitChan chan int64) {
    for job := range workerChan {
        log.Printf("Doing work on job rowInfo ID: %d", job.id)

        // Finish job
        exitChan <- job.id
    }
}

谢谢。

EN

回答 1

Stack Overflow用户

发布于 2016-02-11 16:50:58

该错误告诉您:所有goroutines都处于休眠状态,程序已死锁。

为什么你所有的大猩猩都睡着了?让我们逐一检查它们:

  • worker goroutines:无限期地等待workerChan上的新工作,直到workerChan关闭才会退出,每当它等待新工作时休眠
  • dispatcher goroutine:永远循环,选择超过两个通道。永远不会退出,在select
  • the main goroutine中等待时处于睡眠状态:在time.Sleep上永远循环,永远不会退出,大部分时间处于睡眠状态

通常,在这种情况下,你会引入一个chan struct{} (称之为closing或类似的东西),并在你的select中倾斜它。如果你想关闭程序,只需close(closing)select将选择<-closing选项,您将返回goroutines。您还应该添加一个sync.WaitGroup,以便在所有goroutine都退出时收到通知。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35334035

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档