坚持Go并发

时间:2015-05-05 19:57:45

标签: go channel goroutine

我似乎无法弄清楚下一步该做什么。我的目标是使用图像包中的SubImage函数从原始图像创建所有子图像的数组。我能够在imageSplit()函数中对图像进行分区,并通过通道传递给imageReceiver()函数。

我实际上是在函数imageReceiver()中接收数据,但我不知道如何在接收到来自imageSplit()函数的所有图像后附加到数组并使用它。

// Partitions Image
func Partition(src image.Image) []image.Image {

    newImg := image.NewNRGBA64(src.Bounds())

    r := newImg.Rect
    dx, dy := r.Dx(), r.Dy()

   // partitionNum
   pNum := 3

    // partition x
    px, py := (dx / pNum), (dy / pNum)

    imgChan := make(chan image.Image)
    imgStorage := make([]image.Image, 0)

    for i := 1; i < pNum; i++ {
        for j := 1; j < pNum; j++ {
            startX, startY := ((px * i) - px), ((py * j) - py)
            endX, endY := (px * i), (py * j)

            go imageSplit(imgChan, newImg, startX, startY, endX, endY)
            go imageReceiver(imgChan)
        }
    }

    return imgStorage

}

// Creates sub-images of img
func imageSplit(imgChan chan image.Image, img *image.NRGBA64, startX, startY, endX, endY int) {
    r := image.Rect(startX, startY, endX, endY)
    subImg := img.SubImage(r)

    imgChan <- subImg
}

// Receive sub-image from channel
func imageReceiver(imgChan chan image.Image) {
    img := <-imgChan
    spew.Dump(img.Bounds())
}

我想创建一个全局的image.Image数组,但我不确定这是否是正确的方法来保存&#34;所有子图像。

我想这有点令人困惑的原因是因为这是我第一次在Go中使用并发性。 谢谢你的帮助:)

1 个答案:

答案 0 :(得分:0)

有几种选择可以做到这一点,但我会说你的基本问题是你的接收器没有进行聚合,如果你改变了它,那么它就不会是线程安全的。

修改接收器进行聚合的简单选择是在循环之前分配一个Image数组,并将指针传递给接收器方法,然后在读取通道时使用append。但是你会有一堆不同的goroutines争夺访问同一个数组。实际上,您并不希望聚合是多线程的。如果是,则需要锁定机制才能写入集合。

相反,你想要在循环之后阻止。最简单的方法就是将接收器的主体放在循环之后就行了;

imgs := []image.Image{}
img := <-imgChan
imgs = append(imgs, img)
spew.Dump(img.Bounds())

问题在于现实世界,那么你的软件会阻止该行并且没有响应(无法死亡或退出或任何东西)所以相反,你通常使用频道选择,你至少有2个通道/案例,Partition的调用者可以使用的中止通道,如果需要退出则可以使用它来终止,以及从imgChan接收的案例。那看起来会更像这样;

imgs := []image.Image{}

select {
    case img := <-imgChan
         imgs = append(imgs, img)
         spew.Dump(img.Bounds())
    case _ := <-abortChan:
        return MyCustomError();
    }

这使得你的聚合不是并发的,只有产生结果的工作我个人认为是更好的设计。我也可以解释一下如何锁定接收器方法,但我确信你可以找到很多互斥锁的例子。