为了账号安全,请及时绑定邮箱和手机立即绑定

理解代码:通过交流共享资源

理解代码:通过交流共享资源

Go
慕村9548890 2021-11-01 10:26:15
我一直在尝试理解https://golang.org/doc/codewalk/sharemem/ 中的代码 虽然我得到了关于通过通道传递资源的大部分内容,但我无法理解程序运行的无限循环. 当 poller 函数中的“in”通道(从 main 函数接收)只运行 3 个 poller go 例程时,程序如何无限执行 Poller 函数?我得到 StateMonitor 具有无限循环匿名 go 函数的想法。但是它不能在没有从轮询函数接收的情况下更新 LogState。我假设程序无限地执行对 url 的 Get 请求。为了确认我的理解没有错,我通过打开和关闭 wifi 来测试该程序,以查看日志是否发生变化。令我惊讶的是,它确实进行了几次迭代,但之后它停止响应我的更改并继续显示相同的日志。那么,这是否意味着程序有问题?还是我没有理解一些基本概念?
查看完整描述

3 回答

?
aluckdog

TA贡献1847条经验 获得超7个赞

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

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

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

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


查看完整回答
反对 回复 2021-11-01
?
慕田峪7331174

TA贡献1828条经验 获得超13个赞

当轮询函数中的“in”通道(从主函数接收)仅运行 3 个轮询 go 例程时,程序如何无限执行轮询函数?


因此,首先该程序创建两个轮询器:


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. 有两个 Poller 阅读资源。

  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 继续。

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


查看完整回答
反对 回复 2021-11-01
  • 3 回答
  • 0 关注
  • 174 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信