等待组和无缓冲通道的竞争状况

等待组和无缓冲通道的竞争状况

本文介绍了等待组和无缓冲通道的竞争状况的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在这篇文章中获得了(我的)最初问题的(正确)解决方案后了解golang渠道:僵局,我想出了一个略有不同的解决方案(我认为这样读起来更好:

After getting (the right) solution to my initial problem in this post Understanding golang channels: deadlock, I have come up with a slightly different solution (which in my opinion reads better:

// Binary histogram counts the occurences of each word.
package main

import (
    "fmt"
    "strings"
    "sync"
)

var data = []string{
    "The yellow fish swims slowly in the water",
    "The brown dog barks loudly after a drink ...",
    "The dark bird bird of prey lands on a small ...",
}

func main() {
    histogram := make(map[string]int)
    words := make(chan string)
    var wg sync.WaitGroup
    for _, line := range data {
        wg.Add(1)
        go func(l string) {
            for _, w := range strings.Split(l, " ") {
                words <- w
            }
            wg.Done()
        }(line)
    }

    go func() {
        for w := range words {
            histogram[w]++
        }
    }()
    wg.Wait()
    close(words)

    fmt.Println(histogram)
}

它确实有效,但不幸的是,它在比赛中运行,它显示了2种比赛条件:

It does work, but unfortunately running it against race, it shows 2 race conditions:

==================
WARNING: DATA RACE
Read at 0x00c420082180 by main goroutine:
...
Previous write at 0x00c420082180 by goroutine 9:
...
Goroutine 9 (running) created at:
  main.main()

您能帮助我了解比赛条件在哪里吗?

Can you help me understand where is the race condition?

推荐答案

您正试图从未同步到的 fmt.Println(histogram)中的 histogram 中读取将goroutine修改为 histogram [w] ++ 的代码.您可以添加锁以同步写入和读取.

You are trying to read from histogram in fmt.Println(histogram) which is not synchronized to the write of the goroutine mutating it histogram[w]++. You can add a lock to synchronize the writes and reads.

例如

var lock sync.Mutex

go func() {
    lock.Lock()
    defer lock.Unlock()
    for w := range words {
        histogram[w]++
    }
}()

//...
lock.Lock()
fmt.Println(histogram)

请注意,您也可以使用 sync.RWMutex .

Note you can also use a sync.RWMutex.

您可以做的另一件事是等待goroutine变异 histogram 完成.

Another thing you could do is to wait for the goroutine mutating histogram to finish.

var histWG sync.WaitGroup
histWG.Add(1)
go func() {
    for w := range words {
        histogram[w]++
    }
    histWG.Done()
}()

wg.Wait()
close(words)
histWG.Wait()

fmt.Println(histogram)

或者只是使用频道来等待.

Or simply use a channel to wait.

done := make(chan bool)
go func() {
    for w := range words {
        histogram[w]++
    }
    done <- true
}()

wg.Wait()
close(words)
<-done

fmt.Println(histogram)

这篇关于等待组和无缓冲通道的竞争状况的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-23 17:13