各位前輩好:
我看到一個例子,程式碼如下:
package main
import (
"fmt"
"sync"
)
func addByShareMemory(n int) []int {
var ints []int
var wg sync.WaitGroup
wg.Add(n)
for i := 0; i < n; i++ {
go func(i int) {
defer wg.Done()
ints = append(ints, i)
}(i)
}
wg.Wait()
return ints
}
func main() {
foo := addByShareMemory(10)
fmt.Println(len(foo))
fmt.Println(foo)
}
執行結果如下:
9
[9 4 5 6 7 8 1 0 2]
想請問各位前輩先進,不是應該會有10個值嗎? 而且每次執行結果都不太一樣?
另一次執行結果如下: 我是在go playground中執行,謝謝
5
[9 2 3 4 1]
問題:race conditon
ints 這個陣列在goroutine裡面再append的時候沒有加上lock
所以你每次執行的時候結果都不一樣
解法:
1.在goroutine加上lock
func addByShareMemory(n int) []int {
var ints []int
var wg sync.WaitGroup
var mut sync.Mutex
wg.Add(n)
for i := 0; i < n; i++ {
go func(i int) {
defer wg.Done()
mut.Lock()
ints = append(ints, i)
mut.Unlock()
}(i)
}
wg.Wait()
return ints
}
2.用channel傳送要append的value
func addByShareMemory(n int) []int {
var ints []int
var wg sync.WaitGroup
var ch = make(chan int)
wg.Add(n)
go func() {
for i := 0; i < n; i++ {
ch <- i
}
close(ch)
}()
for val := range ch {
ints = append(ints, val)
wg.Done()
}
wg.Wait()
return ints
}
更新3.mutiple sender 用select承接
func addByShareMemory(n int) []int {
var ints []int
var wg sync.WaitGroup
var ch = make(chan int)
var done = make(chan int)
wg.Add(n)
for i := 0; i < n; i++ {
go func(i int) {
ch <- i
wg.Done()
}(i)
}
go func() {
wg.Wait()
done <- 0
}()
LOOP:
for {
select {
case val, ok := <-ch:
if ok {
ints = append(ints, val)
}
case <-done:
break LOOP
default:
fmt.Println("channel is blocking")
}
}
return ints
}