2013-03-19 59 views
4

我在go中遇到了死锁问题。在Go中发生死锁,两个例程拆分工作

这个程序需要一个int数组,并将它分成两部分。然后它将这两部分分成两个不同的例程并总结所有元素。在此之后,它应该在频道资源中发送两个结果。这两个资源(现在通道)应该加在一起并打印。

我的问题:我试图通过移动关闭函数来解决死锁问题,但似乎没有任何帮助。它运行良好,只有一个例程显然增加运行。

package main 

import (
    "fmt" 
) 

// Add adds the numbers in a and sends the result on res. 
func Add(a []int, res chan<- int) { 
    sum := 0 
    for i := range a { 
     sum = sum + a[i] 
    } 
    res <- sum 
} 

func main() { 
    a := []int{1, 2, 3, 4, 5, 6, 7} 

    n := len(a) 
    ch := make(chan int) 
    go Add(a[:n/2], ch) 
    go Add(a[n/2:], ch) 


    sum := 0 
    for s := range ch { 
     sum = sum + s 
    } 
    //close(ch) 

    fmt.Println(sum) 
} 

回答

4

你永远不会关闭通道,所以range没有信号退出。它只会继续尝试接收,但没有任何东西可以发送。

你要么需要有某种方式让您Add()功能,看它结束的时候,如果是这样,它可以close()通道,或者你可以只递减计数器,而不是在循环使用range的最后一个如此你不需要使用close()

func main() { 
    a := []int{1, 2, 3, 4, 5, 6, 7} 

    n := len(a) 
    ch := make(chan int) 
    go Add(a[:n/2], ch) 
    go Add(a[n/2:], ch) 

    sum := 0 

    // counts the number of messages sent on the channel 
    count := 0 

    // run the loop while the count is less than the total number of routines 
    for count < 2 { 
     s := <-ch 
     sum = sum + s 
     count++ // Increment the count after a routine sends its value 
    } 
    fmt.Println(sum) 
} 

DEMO:http://play.golang.org/p/oHcrUStjmm

+0

谢谢!很简单!我只专注于使用范围,它使我失明。 – user2188724 2013-03-20 00:07:33

+0

不客气。 – 2013-03-20 00:14:26

+2

在这种情况下,可以进一步简化:从总结起始的初始化,您只需要一行:'sum:= <-ch + <-ch'。见http://play.golang.org/p/sVt_82KPuP – 2013-03-20 22:37:28