Hung goroutines when comparing two slices in two separate goroutines and using sync.Waitgroup

huangapple go评论105阅读模式
英文:

Hung goroutines when comparing two slices in two separate goroutines and using sync.Waitgroup

问题

我正在学习goroutines,并在两个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只是一个函数,如果值存在于切片中,则返回一个布尔值。

然而,这个程序卡在只打印一个值上,我不确定为什么会这样。这两个切片都有接近1000个值,并且都是唯一的。代码有什么问题?

英文:

I was learning goroutines, and was comparing two slices to each other in two goroutines, which is in an infinite loop to compare it forever, which may not be the best example to use, and I couldn't figure out why it is hung.

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

Function FindinFirst is

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

	}
}
}

Function FindinSecond is

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

	}
}
}

And IfExists is just a function which return a bool if the value exists in the slice.

However, the routine is stuck with just one value that is being printed, and I am not sure why it is happening. Both the slices has close to 1000 values, and both has uniques. What is wrong with the code?

答案1

得分: 2

我认为在这里使用等待组没有任何用处...因为你正在一个循环中消耗通道,放置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
        }
    }
}

希望能对你有所帮助!

英文:

I don't think there is any use of using wait groups here... Since you are consuming the channels inside a for loop, putting wg.wait() will block untill all the wait groups are completed.

In this cases, putting a value into AddChan will block unless some one is waiting for it. The code works just for first case, after which it hangs.

You can remove the wg.wait() and outer for loop and it will work.

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

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

huangapple
  • 本文由 发表于 2016年4月21日 17:56:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/36766066.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定