0

我一直在尝试理解 https://golang.org/doc/codewalk/sharemem/中的代码 虽然我得到了关于通过通道传递资源的大部分内容,但我无法理解程序运行的无限循环. 当 poller 函数中的“in”通道(从 main 函数接收)只运行 3 个 poller go 例程时,程序如何无限执行 Poller 函数?

我知道 StateMonitor 具有无限循环的匿名 go 函数。但是如果没有从 Poller 函数接收,它就无法更新 LogState。我假设程序无限执行对 url 的 Get 请求。

为了确认我所理解的没有错,我通过打开和关闭 wifi 来测试程序以查看日志是否更改。令我惊讶的是,它确实进行了几次迭代,但之后它停止响应我的更改并继续显示相同的日志。那么,这是否意味着程序有问题?还是我没有理解一些基本概念?

4

3 回答 3

0

当 poller 函数中的“in”通道(从 main 函数接收)只运行 3 个 poller go 例程时,程序如何无限执行 Poller 函数?

所以,首先程序创建两个轮询器:

for i := 0; i < numPollers; i++ {
    go Poller(pending, complete, status)
}

然后它将三个资源发送到待处理:

for _, url := range urls {
    pending <- &Resource{url: url}
}

每个轮询器都从挂起中读取并轮询资源:

for r := range in {
    s := r.Poll()
    status <- State{r.url, s}
    out <- r
}

这段代码似乎是无限执行的,但它通常会阻止从队列中读取。所以这个循环等待下一个值出现。

让我们虚拟地跨过它:

  1. 有两个 Pollers 阅读资源。
  2. 程序将第一个资源发送到队列。
  3. 其中一个轮询器获取资源并开始池化。另一个等着。
  4. 在某个时刻,程序将新资源发送到队列。
  5. 由于第一个轮询器很忙,第二个轮询器被解除阻塞并开始轮询。
  6. 当两个轮询器忙时,程序发送第三个资源和块。
  7. 当其中一个轮询器完成时,它会获取最后一个资源并继续。
  8. 同时,主程序从完整队列中读取值。

for r := range in { s := r.Poll() status <- State{r.url, s} out <- r }这段代码如何无限运行?如果它在“in”通道上循环,并且“in”从待处理队列中获取资源,它应该在几次迭代后终止。我想这正是我不明白的部分。

准确地说,in不从pending队列中获取资源。in pending队列。队列(或通道,我可以互换使用)可以通过调用close来关闭,但在没有明确关闭之前,它被认为是活动的。从它读取的任何内容都会阻塞当前的 goroutine,直到给出下一个值。然后 gorotine 继续。

我想您一直在考虑通道,就像它们是具有固定数量元素的数组一样。他们不是。考虑他们喜欢具有无限数量元素的数组,但具有可能引发异常的阻塞读取(如果您不熟悉该概念,则关闭队列的粗略近似值)。

于 2015-08-07T11:29:18.000 回答
0

通道上的发送操作会阻塞,直到接收器可用于同一通道:如果通道上的值没有接收者,则不能将其他值放入通道中。反之亦然:当通道不为空时,无法在通道中发送新值!所以发送操作将等到通道再次可用。

另一方面,通道的接收操作会阻塞,直到发送方可用于同一通道:如果通道中没有值,则接收方会阻塞。

要解锁通道,我们需要在无限循环中从通道中提取数据。

这就是为什么程序在无限循环中发送和读取数据的解释。

于 2015-08-07T11:29:48.700 回答
-1

这让我很清楚。睡眠功能实际上导致了无限循环。

https://groups.google.com/forum/#!searchin/golang-nuts/sunil/golang-nuts/FSx8GmoRaNM/Nz9CdSF_zh8J][1]

于 2015-08-11T11:54:47.883 回答