我试图通过编写一小段代码来理解 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()
您的代码有两个问题:
- 您应该在创建 Goroutine 时添加到等待组,而不是在将作业发送到通道时添加
- 当您从频道中读取频道时,该频道将从池中删除。所以当你读取3个通道后,
workerChannel := <-pool
将会阻塞,因为没有其他通道。如果你坚持使用频道的频道,你必须把它放回去:
workerChan := <-pool
workerChan <- job
pool<-workerChan
这样,您就可以将通道的通道用作循环队列
- 关闭
pool
不会有任何效果。您必须关闭pool
中的通道。
以上就是chan chan 构造导致死锁的详细内容,更多请关注编程网其它相关文章!
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
软考中级精品资料免费领
- 历年真题答案解析
- 备考技巧名师总结
- 高频考点精准押题
- 资料下载
- 历年真题
193.9 KB下载数265
191.63 KB下载数245
143.91 KB下载数1148
183.71 KB下载数642
644.84 KB下载数2756