我刚刚开始使用 Go 并发并尝试创建一个调度 go 例程,该例程会将作业发送到在 jobchan 通道上侦听的工作池。如果一条消息通过 dispatchchan 通道进入我的调度函数并且我的其他 go 例程正忙,则该消息将附加到调度程序中的堆栈切片上,并且调度程序将在稍后有工作人员可用时尝试再次发送,和/或没有在 dispatchchan 上收到更多消息。这是因为 dispatchchan 和 jobchan 没有缓冲,并且工作人员正在运行的 go 例程会将其他消息附加到调度程序直到某个点,我不希望工作人员阻塞等待调度程序并造成死锁。这是我到目前为止提出的调度程序代码:
func dispatch() {
var stack []string
acount := 0
for {
select {
case d := <-dispatchchan:
stack = append(stack, d)
case c := <-mw:
acount = acount + c
case jobchan <-stack[0]:
if len(stack) > 1 {
stack[0] = stack[len(stack)-1]
stack = stack[:len(stack)-1]
} else {
stack = nil
}
default:
if acount == 0 && len(stack) == 0 {
close(jobchan)
close(dispatchchan)
close(mw)
wg.Done()
return
}
}
}
完整示例位于https://play.golang.wiki/p/X6kXVNUn5N7
mw 通道是一个缓冲通道,长度与 worker go 例程的数量相同。它充当工作池的信号量。如果工作程序正在执行 [m] 有意义的 [w]ork,它会在 mw 通道上抛出 int 1,当它完成工作并返回 for 循环监听 jobchan 时,它会在 mw 上抛出 int -1。这样,调度程序就知道工作池是否正在完成任何工作,或者该池是否处于空闲状态。如果池空闲并且堆栈上没有更多消息,则调度程序关闭通道并将控制权返回给主函数。
这一切都很好,但我遇到的问题是堆栈本身的长度可能为零,所以在我尝试将堆栈 [0] 发送到 jobchan 的情况下,如果堆栈为空,则会出现越界错误。我想弄清楚的是如何确保当我遇到这种情况时,stack[0] 是否有一个值。我不希望这种情况向 jobchan 发送一个空字符串。
任何帮助是极大的赞赏。如果有我应该考虑的更惯用的并发模式,我很想听听。我不是 100% 相信这个解决方案,但这是迄今为止我所获得的最远距离。
慕村225694
相关分类