理解代码:通过通信共享资源

时间:2015-08-07 11:01:56

标签: go concurrency channels

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

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

为了确认我对我理解的内容没有错,我通过打开和关闭wifi来测试程序以查看日志是否发生变化。令我惊讶的是,对于少数迭代它确实如此,但在此之后它停止响应我的更改并继续显示相同的日志。那么,这是否意味着程序是错误的?还是我不了解一些基本概念?

3 个答案:

答案 0 :(得分:0)

  

当" in"程序如何无限地执行Poller功能? poller函数中的通道(从main函数接收)只运行3个poller go例程?

所以,首先程序会创建两个Pollers:

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

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

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

每个Poller都会从pending中读取并轮询资源:

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

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

让我们实际上跨过它:

  1. 有两个Poller阅读资源。
  2. 程序将第一个资源发送到队列。
  3. 其中一个轮询器获取资源并开始汇集。另一个等待。
  4. 在某个时刻,程序会将新资源发送到队列。
  5. 当第一个轮询器忙时,第二个轮询器被解锁并开始轮询。
  6. 当两个轮询器忙时,程序发送第三个资源和块。
  7. 当其中一个轮询器完成时,它将占用最后一个资源并继续。
  8. 与此同时,主程序从完整队列中读取值。
  9.   

    for r := range in { s := r.Poll() status <- State{r.url, s} out <- r }这段代码如何无限运行?如果它循环过来&#34;在&#34;频道,&#34; in&#34;从待处理队列获取其资源,它应该在几次迭代后终止。我认为这正是我不理解的部分。

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

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

答案 1 :(得分:0)

通道上的发送操作会阻塞,直到接收器可用于同一通道:如果通道上的值没有接收者,则不能在通道中放入其他值。反过来说:当频道不为空时,不能在频道中发送新值!因此,发送操作将一直等到通道再次可用。

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

要取消阻止频道,我们需要在无限循环中从频道中提取数据。

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

答案 2 :(得分:-1)

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

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