【发布时间】:2018-04-30 17:20:02
【问题描述】:
我正在编写一个允许用户上传文件并将它们排队等待处理的应用程序。我的方法是创建一个 goroutine 来处理上传的文件,并使用一个通道来表示一个新文件已准备好进行处理。
处理 goroutine 基本上是这样做的:
for {
while itemForProcessing() {
processNextItem()
}
select {
case <-signalChan:
case <-stopChan:
return
}
}
表示新项目已准备好进行处理的代码如下所示:
select {
case signalChan <- true:
default:
}
请注意,这是通道上的非阻塞发送。
有三种可能的情况:
- 处理 goroutine 在
select{}块中 - 第一个案例运行并处理下一个项目 - 处理goroutine正在执行
processNextItem()——下一项将在processNextItem()返回后处理,因为循环条件将是true - 处理 goroutine 已退出循环但尚未进入
select{}块
最后一种情况会导致问题。非阻塞发送不会在通道上发送任何内容,goroutine 将在 select{} 块中等待,直到发生其他事情。
如何避免这个问题?我不能使用阻塞发送,因为处理 goroutine 可能正在运行 processNextItem(),这会导致发送阻塞很长时间。
【问题讨论】:
-
这里的频道作为一个可更新的标志 - 表明应用程序可以读取某些内容。我想有可能简化事情 - 只需通过通道传递新对象进行处理。这解决了几个问题:简单的并行性、竞争条件保护、简化。
标签: go race-condition channel