【问题标题】:Understanding the code : Sharing resources by communicating理解代码:通过通信共享资源
【发布时间】:2015-08-07 11:01:56
【问题描述】:

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

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

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

【问题讨论】:

    标签: go concurrency channels


    【解决方案1】:

    当 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}
    }
    

    每个 Poller 都从待处理的资源中读取并轮询资源:

    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 &lt;- State{r.url, s} out &lt;- r }这段代码如何无限运行?如果它在“in”通道上循环,并且“in”从待处理队列中获取资源,它应该在几次迭代后终止。我想这正是我不明白的部分。

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

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

    【讨论】:

    • for r := range in { s := r.Poll() status &lt;- State{r.url, s} out &lt;- r }这段代码如何无限运行?如果它在“in”通道上循环,并且“in”从待处理队列中获取资源,它应该在几次迭代后终止。我想这正是我不明白的部分。尤其是本节中正在进行的交流。感谢您的逐步解释。
    【解决方案2】:

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

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

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

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

    【讨论】:

    • 如果我错了,请纠正我。程序中只有一个无限循环,它位于 SateMonitor 函数内部。如果我能够理解 StateMonitor 函数如何与 Poller 函数交互,那对我来说完全有意义。
    【解决方案3】:

    这让我很清楚。 sleep 函数实际上导致了无限循环。

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

    【讨论】:

      猜你喜欢
      • 2020-06-27
      • 2016-07-23
      • 2017-10-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-12
      相关资源
      最近更新 更多