首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >理解代码- Go并发模式:雏菊链

理解代码- Go并发模式:雏菊链
EN

Stack Overflow用户
提问于 2014-10-01 06:49:39
回答 2查看 1.9K关注 0票数 4

我在研究围棋并发模式。

我不确定的一个模式是:黛西链https://talks.golang.org/2012/concurrency.slide#39

对我来说,很难理解代码的控制流。

有人能跟我解释一下吗?

代码语言:javascript
复制
package main

import (
    "fmt"
)

func f(left, right chan int) {
    left <- 1 + <-right
}

func main() {
    const n = 10000

    leftmost := make(chan int)
    right := leftmost               //point B: what does these do ?
    left := leftmost

    for i := 0; i < n; i++ {
        right = make(chan int)
        go f(left, right)
        left = right                //point A
    }
    go func(c chan int) { c <- 1 }(right)  
    fmt.Println(<-leftmost)
}

结论

  1. 由右向左流动的通道。编写func f(left chan<- int, right <-chan int)是很好的实践,而不是上面提到的原始函数签名。
  2. “链式反应”直到c <- 1才开始,当信号1被发送到最右边的通道时,反应一直持续到最左边。打印10001。

原因是去通道块‘读’直到接收到的信道接收信号。

  1. @Rick-777展示了如何使用类似数组的结构,以便于理解。因为每个围棋的协同线只有大约6k大。制作10k频道是个不错的主意。
  2. 我清理了点B周围的一些代码,用于通道初始化。下面是源代码:http://play.golang.org/p/1kFYPypr0l
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-10-02 11:28:29

VonC已经给出了一个直接的答案。以下是一些进一步的评论。

一个稍微整洁的版本是在操场中,不同的是作为参数传递的通道具有显式指定的方向。<-chanchan<-.这样做是很好的做法,因为编译器可以为您捕获更多的错误。

是一种替代的、等价的程序,它有一条n大猩猩的雏菊链,可以使用一组通道来编写。这将使用较少的代码行分配相同的信道总数。请参阅游乐场

代码语言:javascript
复制
package main

import (
    "fmt"
)

func f(left chan<- int, right <-chan int) {
    left <- 1 + <-right
}

func main() {
    const n = 10000

    // first we construct an array of n+1 channels each being a 'chan int'
    var channels [n+1]chan int
    for i := range channels {
        channels[i] = make(chan int)
    }

    // now we wire n goroutines in a chain
    for i := 0; i < n; i++ {
        go f(channels[i], channels[i+1])
    }

    // insert a value into the right-hand end
    go func(c chan<- int) { c <- 1 }(channels[n])

    // pick up the value emerging from the left-hand end
    fmt.Println(<-channels[0])
}

我希望你现在能看到原来的程序是如何等同于这个程序的。有一个小的区别:最初的程序不创建任何通道数组,所以使用的内存稍微少一点。

票数 7
EN

Stack Overflow用户

发布于 2014-10-01 06:59:45

它说明了你可以产生大量的猩猩。

在这里,每个go f(left, right)块:left <- 1 + <-right块,因为它等待right获取一个值。见"高朗频道维持秩序吗?“。

这里创建的所有通道都是未缓冲的通道。

所有10000条峡谷都被创造出来了。

B点:使用rightleft声明短变量声明

  • right被初始化到最左边,但这并不重要,因为它将被重新分配到for循环(right = make(chan int))中的一个新通道。 宣布权利的另一种方式是: 右陈int
  • left是用leftmost初始化的,这是创建的第一个通道。

点A:但是一旦通道开始等待(left <- 1 + <-right),for循环就被设置为right,并创建了一个新的right:这就是雏菊链的构建方式

代码语言:javascript
复制
 left <- (new) right (now left) <- (new) right (now left) <- ...

然后,将一个值发送到创建的最后一个right通道:{c <- 1 }(right)

然后等待为接收其值而创建的第一个leftmost通道(递增10000倍)。

因为接收者总是阻塞直到有数据要接收,所以main()函数本身在leftmost最终接收到它的值之前不会退出。

如果main()过早退出,雏菊链就没有时间完成了。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26135616

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档