工人goroutine的项目队列的正确方式



我正在编写一个应用程序,该应用程序允许用户上传文件并对其进行排队处理。我的方法是创建一个goroutine来处理上传的文件,并使用一个通道来表示新文件已准备好进行处理。

基本上,处理goroutine是这样做的:

for {
while itemForProcessing() {
processNextItem()
}
select {
case <-signalChan:
case <-stopChan:
return
}
}

用于发出新项目准备处理的信号的代码如下所示:

select {
case signalChan <- true:
default:
}

请注意,这是通道上的非阻塞发送。

有三种可能的情况:

  • 处理goroutine在select{}块中—运行第一个案例并处理下一个项目
  • 处理goroutine正在执行CCD_ 2—一旦processNextItem()返回,下一个项目将被处理,因为循环条件将是true
  • 处理goroutine已退出循环,但尚未进入select{}

最后一种情况将导致问题。非阻塞发送不会在信道上发送任何内容,goroutine将在select{}块中等待,直到发生其他事情。

我该如何避免这个问题?我不能使用阻塞发送,因为处理goroutine可能正在运行processNextItem(),这将导致发送在很长一段时间内阻塞。

要避免信号丢失,请使用容量为1的通道。

最新更新