理解代码:通过交流共享资源
Understanding the code : Sharing resources by communicating
我一直在努力理解中的代码
https://golang.org/doc/codewalk/sharemem/
虽然我了解了大部分关于通过通道传递资源的部分,但我无法理解程序 运行 中的无限循环。当轮询器中的 "in" 通道时,程序如何无限执行 Poller 函数函数(从主函数接收)运行 只有 3 个轮询器执行例程?
我想到了 StateMonitor 具有无限循环的匿名 go 函数。但它无法在不从 Poller 函数接收的情况下更新 LogState。我假设程序无限地对 url 执行 Get 请求。
为了确认我所理解的没有错,我通过打开和关闭 wifi 来测试程序以查看日志是否发生变化。令我惊讶的是,它确实如此,进行了几次迭代,但之后它停止响应我的更改并继续显示相同的日志。那么,这是否意味着程序有问题?还是我没有理解一些基本概念?
How does the program execute Poller function infinitely when the "in" channel in poller function(that receives from main function) run only 3 poller go routines ?
因此,程序首先创建两个轮询器:
for i := 0; i < numPollers; i++ {
go Poller(pending, complete, status)
}
然后发送三个资源到pending:
for _, url := range urls {
pending <- &Resource{url: url}
}
每个 Poller 从 pending 中读取并轮询资源:
for r := range in {
s := r.Poll()
status <- State{r.url, s}
out <- r
}
这段代码似乎是无限执行的,但它通常会阻塞从队列中读取。所以这个循环等待下一个值出现。
让我们虚拟地跨过它:
- 有两个Poller读取资源
- 程序将第一个资源发送到队列。
- 其中一个轮询器获取资源并开始池化。另一个等待。
- 有时程序会向队列发送新资源。
- 由于第一个轮询器忙,第二个轮询器解除阻塞并开始轮询。
- 程序发送第三个资源并阻塞,因为两个轮询器正忙。
- 当其中一个轮询器完成时,它会占用最后一个资源并继续。
- 同时,主程序从完整队列中读取值。
for r := range in { s := r.Poll() status <- State{r.url, s} out <- r }
How does this code run infinitely? If it loops over "in" channel, and "in" gets its resources from pending queue, it should terminate after few iterations. I think this is exactly the part that I don't understand.
准确的说,in
并没有从pending
队列中获取资源。 in
是 pending
队列。队列(或通道,我可以互换使用)可以通过调用 close 来关闭,但在未明确关闭之前,它被认为是活动的。从它读取的任何内容都会阻塞当前的 goroutine,直到给出下一个值。然后 gorotine 恢复。
我想你一直在考虑通道,就像它们是具有固定数量元素的数组一样。他们不是。考虑他们喜欢具有无限数量元素的数组,但阻塞读取可能会抛出异常(如果您不熟悉这个概念,则粗略地近似关闭队列)。
通道上的发送操作会阻塞,直到同一通道有可用的接收方:如果通道上的值没有接收方,则不能将其他值放入通道中。反之亦然:当通道不为空时,不能在通道中发送新值!因此发送操作将等到通道再次可用。
另一方面,通道的接收操作会阻塞,直到发送方可用于同一通道:如果通道中没有值,则接收方会阻塞。
要解锁通道,我们需要无限循环地从通道中提取数据。
这就是为什么程序在无限循环中发送和读取数据的解释。
这让我明白了。休眠函数实际上会导致无限循环。
我一直在努力理解中的代码 https://golang.org/doc/codewalk/sharemem/ 虽然我了解了大部分关于通过通道传递资源的部分,但我无法理解程序 运行 中的无限循环。当轮询器中的 "in" 通道时,程序如何无限执行 Poller 函数函数(从主函数接收)运行 只有 3 个轮询器执行例程?
我想到了 StateMonitor 具有无限循环的匿名 go 函数。但它无法在不从 Poller 函数接收的情况下更新 LogState。我假设程序无限地对 url 执行 Get 请求。
为了确认我所理解的没有错,我通过打开和关闭 wifi 来测试程序以查看日志是否发生变化。令我惊讶的是,它确实如此,进行了几次迭代,但之后它停止响应我的更改并继续显示相同的日志。那么,这是否意味着程序有问题?还是我没有理解一些基本概念?
How does the program execute Poller function infinitely when the "in" channel in poller function(that receives from main function) run only 3 poller go routines ?
因此,程序首先创建两个轮询器:
for i := 0; i < numPollers; i++ {
go Poller(pending, complete, status)
}
然后发送三个资源到pending:
for _, url := range urls {
pending <- &Resource{url: url}
}
每个 Poller 从 pending 中读取并轮询资源:
for r := range in {
s := r.Poll()
status <- State{r.url, s}
out <- r
}
这段代码似乎是无限执行的,但它通常会阻塞从队列中读取。所以这个循环等待下一个值出现。
让我们虚拟地跨过它:
- 有两个Poller读取资源
- 程序将第一个资源发送到队列。
- 其中一个轮询器获取资源并开始池化。另一个等待。
- 有时程序会向队列发送新资源。
- 由于第一个轮询器忙,第二个轮询器解除阻塞并开始轮询。
- 程序发送第三个资源并阻塞,因为两个轮询器正忙。
- 当其中一个轮询器完成时,它会占用最后一个资源并继续。
- 同时,主程序从完整队列中读取值。
for r := range in { s := r.Poll() status <- State{r.url, s} out <- r }
How does this code run infinitely? If it loops over "in" channel, and "in" gets its resources from pending queue, it should terminate after few iterations. I think this is exactly the part that I don't understand.
准确的说,in
并没有从pending
队列中获取资源。 in
是 pending
队列。队列(或通道,我可以互换使用)可以通过调用 close 来关闭,但在未明确关闭之前,它被认为是活动的。从它读取的任何内容都会阻塞当前的 goroutine,直到给出下一个值。然后 gorotine 恢复。
我想你一直在考虑通道,就像它们是具有固定数量元素的数组一样。他们不是。考虑他们喜欢具有无限数量元素的数组,但阻塞读取可能会抛出异常(如果您不熟悉这个概念,则粗略地近似关闭队列)。
通道上的发送操作会阻塞,直到同一通道有可用的接收方:如果通道上的值没有接收方,则不能将其他值放入通道中。反之亦然:当通道不为空时,不能在通道中发送新值!因此发送操作将等到通道再次可用。
另一方面,通道的接收操作会阻塞,直到发送方可用于同一通道:如果通道中没有值,则接收方会阻塞。
要解锁通道,我们需要无限循环地从通道中提取数据。
这就是为什么程序在无限循环中发送和读取数据的解释。
这让我明白了。休眠函数实际上会导致无限循环。