文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

chan chan 构造导致死锁

2024-02-06 05:26

关注

问题内容

我试图通过编写一小段代码来理解 Go 中的 chan chan 构造,如下所示,我希望 3 个工作子例程处理 10 个作业。每个工作子例程都有自己的通道,在其中接收要处理的“作业”。主 Go 例程通过从通道池中获取通道(因此是 chan chan 构造)来将作业分发到工作通道。

但是这段代码会导致死锁情况!我尝试了此代码的一些变体,但遇到了相同的错误。

是否是因为工作子例程永远等待从其通道读取作业?或者是由于其他原因(也许通道过早关闭等)?我对整个结构的理解显然遗漏了一些东西。

有人可以帮我理解这个问题以及如何解决它吗?

游乐场中的代码,并根据要求复制到下面。

package main

import (
    "fmt"
    "sync"
)

type Job struct {
    ID int
}

func worker(id int, jobs <-chan Job, wg *sync.WaitGroup) {
    defer wg.Done()
    fmt.Printf("Worker %d starting\n", id)
    for job := range jobs {
        fmt.Printf("Worker %d processing job %d\n", id, job.ID)
    }
    fmt.Printf("Worker %d done\n", id)
}

func main() {
    numWorkers := 3
    maxJobs := 10
    var wg sync.WaitGroup
    // Create the pool of worker channels
    pool := make(chan chan Job, numWorkers)

    for i := 0; i < numWorkers; i++ {
        workerChan := make(chan Job) // Create a new channel for each worker
        pool <- workerChan           // Add the worker channel to the pool
        go worker(i, workerChan, &wg)
    }
    defer close(pool)
    // Create jobs and distribute them to workers
    for i := 0; i < maxJobs; i++ {
        job := Job{ID: i}
        wg.Add(1)
        workerChan := <-pool
        workerChan <- job
    }

    // Wait for all workers to complete
    wg.Wait()
    fmt.Println("All jobs are processed")
}


正确答案


首先:这里不需要一个频道的频道。要将工作分配给多个工作人员,您只需让所有工作人员从单个共享通道读取即可。当您向通道发送一件工作时,如果有可用的工作人员,其中一个将接收它,否则,通道发送操作将阻塞,直到有一个可用的工作人员为止。

如果您想为每个工作人员使用单独的通道,您仍然不需要通道的通道,您只需要其中的一部分即可。每个工作人员都将从专用渠道收听,您将自行管理工作分配:

numWorkers := 3
maxJobs := 10
var wg sync.WaitGroup
pool := make([]chan Job, numWorkers)
for i := 0; i < numWorkers; i++ {
    pool[i] = make(chan Job)
    wg.Add(1)
    go worker(i, pool[i], &wg)
}
for i := 0; i < maxJobs; i++ {
   job := Job{ID: i}
   pool[i%len(pool)] <- job
}
for _,c:=range pool {
   close(c)
}
wg.Wait()

您的代码有两个问题:

  1. 您应该在创建 Goroutine 时添加到等待组,而不是在将作业发送到通道时添加
  2. 当您从频道中读取频道时,该频道将从池中删除。所以当你读取3个通道后, workerChannel := <-pool 将会阻塞,因为没有其他通道。如果你坚持使用频道的频道,你必须把它放回去:
workerChan := <-pool
 workerChan <- job
 pool<-workerChan

这样,您就可以将通道的通道用作循环队列

  1. 关闭 pool 不会有任何效果。您必须关闭 pool 中的通道。

以上就是chan chan 构造导致死锁的详细内容,更多请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 资料下载
  • 历年真题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯