go - 在两个单独的 goroutine 中比较两个 slice 并使用 sync.Waitgroup 时挂起 goroutines

标签 go concurrency channel goroutine

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

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 只是一个函数,如果该值存在于 slice 中,它会返回一个 bool 值。

但是,该例程只停留在一个正在打印的值上,我不确定为什么会这样。这两个 slice 都有接近 1000 个值,并且都有唯一性。代码有什么问题?

最佳答案

我认为在这里使用 WaitGroup 没有任何用处...因为您在 for 循环中使用 channel ,放置 wg.wait() 将阻塞直到所有 WaitGroup 完成。

在这种情况下,将值放入 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
        }
    }
}

关于go - 在两个单独的 goroutine 中比较两个 slice 并使用 sync.Waitgroup 时挂起 goroutines,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36766066/

相关文章:

java - 从 URL 读取奇怪的 byte[] 行为

firebase - 在 Golang 中仅使用环境变量初始化 Firebase Admin SDK

映射并发访问

c# - 没有并发检查的 Entity Framework IsRowVersion()

Go 的 sync.WaitGroup 丢失了其中一个响应

multithreading - 接收器在尝试通过 channel 发送时关闭并返回 SendError

go - 选择忽略慢的情况?

go - os.FileInfo 是否主动查询文件系统,或者是此类查询的结果?

arrays - Golang,将嵌入式结构转换为数组

java - Replicated Workers 范例中更多线程的随机结果