使用频道或同步.康德等待条件



我正在尝试等待特定条件,我想了解如何最好地做到这一点。我有一个看起来像这样的结构(简化):

type view struct {
    timeFrameReached bool
    Rows []*sitRow
}

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

在其他地方,我想等待以下条件为真:

view.timeFrameReached == true || len(view.Rows) >= numRows

我正在尝试学习通道以及 Go 的条件变量如何工作,我想知道这里的最佳解决方案是什么。从理论上讲,我可以做一些像这样微不足道的事情:

for {
    view = getView()
    if view.timeFrameReached == true || len(view.Rows) >= numRows {
        break
    }
}

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

我想

我会用条件变量来做到这一点。这个概念并不是说只有当服务员想要检查的条件为真时,才应该进行Signal,而是当它可能为真时(即,被检查的东西已经改变)。

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

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

然后,在更改view的代码中:

mutex.Lock()
// Change view
cond.Signal() // or cond.Broadcast()
mutex.Unlock()

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

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

我的一个想法涉及通过通道传达所需的行数,构建视图的 goroutine 将执行非阻塞接收以查看主线程是否正在请求一定数量的行。如果是这样,它将发回一条消息,指示满足条件。

在这里,main函数请求许多行:

if numRows > len(viewFile.View.Rows) && !viewFile.View.TimeFrameReached {
    // Send the required number of rows
    rows <- numRows
    // Wait for the prefetch loop to signal that the view file is ready
    <-rows // Discard the response value and move on
    view = getView()
}

在这里,go例程检查是否需要一定数量的行。如果是这样,它会在准备就绪时以肯定信号响应。该信号的值无关紧要。

select {
    case numRows := <-rows:
        if len(viewFile.View.Rows) >= numRows || viewFile.View.TimeFrameReached {
            rows <- 1
        }
    default:
}

最新更新