具有等待组和无缓冲通道的竞争条件
Race condition with waitgroup and unbuffered channel
在 post 中找到我最初问题的(正确)解决方案后,我想出了一个略有不同的解决方案(我认为读起来更好:
// 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 个种族条件:
==================
WARNING: DATA RACE
Read at 0x00c420082180 by main goroutine:
...
Previous write at 0x00c420082180 by goroutine 9:
...
Goroutine 9 (running) created at:
main.main()
你能帮我了解竞争条件在哪里吗?
您正在尝试从 fmt.Println(histogram)
中的 histogram
中读取,这与改变它的 goroutine 的写入不同步 histogram[w]++
。您可以添加一个锁来同步写入和读取。
例如
var lock sync.Mutex
go func() {
lock.Lock()
defer lock.Unlock()
for w := range words {
histogram[w]++
}
}()
//...
lock.Lock()
fmt.Println(histogram)
请注意,您也可以使用 sync.RWMutex
。
您可以做的另一件事是等待 goroutine 变异 histogram
完成。
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)
或者干脆用一个频道等待。
done := make(chan bool)
go func() {
for w := range words {
histogram[w]++
}
done <- true
}()
wg.Wait()
close(words)
<-done
fmt.Println(histogram)
在 post
// 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 个种族条件:
==================
WARNING: DATA RACE
Read at 0x00c420082180 by main goroutine:
...
Previous write at 0x00c420082180 by goroutine 9:
...
Goroutine 9 (running) created at:
main.main()
你能帮我了解竞争条件在哪里吗?
您正在尝试从 fmt.Println(histogram)
中的 histogram
中读取,这与改变它的 goroutine 的写入不同步 histogram[w]++
。您可以添加一个锁来同步写入和读取。
例如
var lock sync.Mutex
go func() {
lock.Lock()
defer lock.Unlock()
for w := range words {
histogram[w]++
}
}()
//...
lock.Lock()
fmt.Println(histogram)
请注意,您也可以使用 sync.RWMutex
。
您可以做的另一件事是等待 goroutine 变异 histogram
完成。
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)
或者干脆用一个频道等待。
done := make(chan bool)
go func() {
for w := range words {
histogram[w]++
}
done <- true
}()
wg.Wait()
close(words)
<-done
fmt.Println(histogram)