当比较两个单独的goroutines中的两个切片并使用sync.Waitgroup时,挂起goroutines

时间:2016-04-21 09:56:35

标签: go concurrency channel goroutine

我正在学习goroutines,并在两个goroutines中比较两个切片,这是一个无限循环来永远地比较它,这可能不是最好的例子,我无法弄清楚为什么它挂了。

for ;; {
    var wg sync.WaitGroup
    wg.Add(2)
    go FindinFirst(&Arr1, &Arr2, AddChan, &wg)
    go FindinSecond(&Arr2, &Arr1, DelChan, &wg)
    counter := 0
        for ; ; {
            select {
            case Add, ok := <- AddChan:
                if ok == true {
                    for k, v := range Add  {
                        fmt.Println(k, ":", v)
                    }
                }else {
                    counter += 1
                }
            case Del, ok := <- DelChan:
                if ok == true {
                    for k, v := range Del  {
                        fmt.Println(k, ":", v)
                    }
                }else {
                    counter += 1
                    }
            }
            if counter == 2{
                break
            }
            wg.Wait()
}

功能FindinFirst是

func FindinFirst(Arr1, Arr2 *[]string, AddChan chan string, wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("Starting FindinFirst")
defer close(AddChan)
for _, i := range *Arr1 {
    if IfExists(i, *Arr2) {
        fmt.Println("Exists")
        continue
    } else {
        AddChan <- i

    }
}
}

函数FindinSecond是

func FindinSecond(Arr2, Arr1 *[]string, DelChan chan string, wg *sync.WaitGroup){
defer wg.Done()
fmt.Println("Starting FindinSecond")
defer close(DelChan)
for _, i := range *Arr2 {
    if IfExists(i, *Arr1) {
        fmt.Println("Exists")
        continue
    } else {
        DelChan <- i

    }
}
}

IfExists只是一个函数,如果切片中存在值,则返回bool。

然而,例程只有一个正在打印的值,我不确定它为什么会发生。两个切片都有接近1000个值,并且两者都具有唯一值。代码有什么问题?

1 个答案:

答案 0 :(得分:2)

我认为在这里使用等待组没有任何用处......由于你正在使用for循环中的通道,所以放置wg.wait()将阻止所有等待组完成。

在这种情况下,将值放入AddChan将阻止,除非有人等待它。该代码仅适用于第一种情况,之后它会挂起。

您可以移除wg.wait()和外部for循环,它将起作用。

func main() {
    Arr1 := []string{"a", "b", "c", "d"}
    Arr2 := []string{"c", "e", "f", "g"}
    AddChan := make(chan string)
    DelChan := make(chan string)

    var wg sync.WaitGroup
    wg.Add(2)
    go FindinFirst(&Arr1, &Arr2, AddChan, &wg)
    go FindinSecond(&Arr2, &Arr1, DelChan, &wg)
    counter := 0
    for {
        select {
        case Add, ok := <-AddChan:
            if ok == true {
               fmt.Println(Add)
            } else {
                counter += 1
            }
        case Del, ok := <-DelChan:
            if ok == true {
                fmt.Println(Del)
            } else {
                counter += 1
            }
        }

        //if both the channels are closed, we are good, hence exit
        if counter == 2 {
            break
        }
    }
}