使用channel或sync.Cond等待条件

Ale*_*ker 6 channel condition-variable go

我正在尝试等待特定的条件,我想了解如何最好地完成此操作的建议。我有一个如下所示的结构(简化):

type view struct {
    timeFrameReached bool
    Rows []*sitRow
}
Run Code Online (Sandbox Code Playgroud)

在 goroutine 中,我正在更新一个文件,该文件被读入view变量中。行数增加,timeFrameReached最终将是true

在其他地方,我想等待以下条件成立:

view.timeFrameReached == true || len(view.Rows) >= numRows
Run Code Online (Sandbox Code Playgroud)

我正在尝试学习通道以及 Go 的条件变量如何工作,我想知道这里最好的解决方案是什么。理论上,我可以做这样的小事:

for {
    view = getView()
    if view.timeFrameReached == true || len(view.Rows) >= numRows {
        break
    }
}
Run Code Online (Sandbox Code Playgroud)

但这显然是一个幼稚的解决方案。的值numRows来自 HTTP 请求,因此条件方法似乎具有挑战性。Goroutine 不知道何时广播条件,因为它不知道它正在查找的行数。

And*_*eig 4

我想我会用条件变量来做到这一点。这个概念并不是Signal只有当服务员想要检查的条件为真时才应执行 a ,而是当它可能为真时(即正在检查的内容已更改)。

执行此操作的正常模式是:

mutex.Lock()
for {
    view = getView()
    if view.timeFrameReached == true || len(view.Rows) >= numRows {
        break
    }
    cond.Wait(&mutex)
}
// Do stuff with view
mutex.Unlock()
Run Code Online (Sandbox Code Playgroud)

然后,在代码中view更改:

mutex.Lock()
// Change view
cond.Signal() // or cond.Broadcast()
mutex.Unlock()
Run Code Online (Sandbox Code Playgroud)

显然,我在不知道您的程序如何工作的情况下编写了此内容,因此您可能需要进行一些更改。

您可以通过在通道上发送信号并尝试从通道接收等待来对通道执行类似的操作,但这对我来说似乎更复杂。(另外,如果你有多个 goroutine 等待,你可以使用 向所有 goroutine 发出唤醒信号cond.Broadcast。)