gpt4 book ai didi

go - 同时从两个 channel 消费会导致 goroutine 占用我的 RAM

转载 作者:数据小太阳 更新时间:2023-10-29 03:08:38 25 4
gpt4 key购买 nike

我对并发很陌生,我决定在 goroutines 中运行我的 http 处理程序的几个部分,它开始占用我的 RAM 并卡住我的计算机。

这就是我想要做的:

我的处理程序有这两个函数调用

qChan := cloneQuestions(currentFormView.QuestionObjects, currentForm.Id, currentForm.VersionNumber, now)

rChan := cloneRules(currentFormView.RuleObjects, currentForm.Id, currentForm.VersionNumber, now)

这两个函数调用都在名为 helpers.go 的文件中定义,它们将结构 channel 返回给调用者。

这是 cloneQuestions 和 clonedRules 的函数定义,遵循与此相同的模式

func cloneQuestions(questions []question.Model, formID string, versionNumber int, now time.Time) <-chan question.Model {
out := make(chan question.Model)

go func() {
for _, currentQuestion := range questions {
out <- getClonedQuestion(currentQuestion, formID, versionNumber, now)
}
close(out)
}()

return out
}

func getClonedQuestion(currentQuestion question.Model, formID string, versionNumber int, now time.Time) question.Model {
newOptionsArray := cloneQuestionOptions(currentQuestion, formID, now)


return currentQuestion
}

cloneRules 和这个很像

在我的处理程序中调用这两个函数并如上所述将它们返回的 channel 存储在 qChan 和 rChan 变量中之后,我运行一个无限循环以同时使用两个 channel 的值,并在我停止从两个 channel 接收值后跳出循环 channel ,这是代码

for {
select {
case clonedQuestion := <-qChan:
insertQuestionToFormTxn := h.service.Mongo.GetAppendTxn(ctx, form.COLLECTION, currentForm.FormID, "questions", clonedQuestion.Id, clonedQuestion.Order)

newQuestionTxn := h.service.Mongo.GetNewTxn(ctx, question.COLLECTION, clonedQuestion, clonedQuestion.Id)
// collect all the txns in the arrray
array = append(array, insertQuestionToFormTxn, newQuestionTxn)
case clonedRule := <-rChan:

newRuleTxn := h.service.Mongo.GetNewTxn(ctx, rule.COLLECTION, clonedRule, clonedRule.Id)
// collect all the txns in the arrray
array = append(array, insertRuleToFormTxn, newRuleTxn)
default:
break
}
}

当我向这个处理程序发出请求并同时运行 htop 时,我看到它开始填满我的 RAM 并卡住了我的机器,为什么会这样?

最佳答案

正如@JimB 建议的那样,从 select 语句中删除 default 子句,因为它会导致紧循环,从而占用您的 CPU。

Select 的可选默认值允许对 channel 进行非阻塞轮询。在您的情况下,您想等待任一 channel 项目。在大多数用例中,阻塞优于轮询。

如果您担心服务会因为阻塞而出现休眠状态,您可以添加一个定时器 channel 以显示活跃度,例如

t := time.NewTicker(time.Minute)
for {
select {
case i := <-ch:
log.Println("got item:", i)
case <-t.C:
log.Println("I'm not dead yet!")
}
}

playground

关于go - 同时从两个 channel 消费会导致 goroutine 占用我的 RAM,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56505336/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com