iT邦幫忙

0

go waitgroup問題...

  • 分享至 

  • xImage

各位前輩好:

我看到一個例子,程式碼如下:

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]
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

1 個回答

3
whitefloor
iT邦研究生 2 級 ‧ 2021-12-20 12:34:06

問題: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
}

我要發表回答

立即登入回答