簡體   English   中英

goroutine 和 Waitgroup 的問題

[英]Issue with goroutine and Waitgroup

我正在嘗試迭代一個循環並在匿名 function 上調用 go 例程,並在每次迭代中添加一個等待組。 並將字符串傳遞給相同的匿名 function 並將值附加到切片a 由於我循環 10000 倍的切片長度預計為 10000。但我看到隨機數。 不確定是什么問題。 誰能幫我解決這個問題?

這是我的代碼片段


import (
    "fmt"
    "sync"
)
func main() {
    var wg = new(sync.WaitGroup)
    var a []string
    for i := 0; i <= 10000; i++ {
        wg.Add(1)
        go func(s string) {

            a = append(a, s)
            wg.Done()
        }("MaxPayne")
    }
    wg.Wait()
    fmt.Println(len(a))
}

請注意如何附加切片,實際上是創建一個新切片,然后將其分配回切片變量。 因此,您可以不受控制地並發寫入變量a 在 Go(和大多數語言)中並發寫入相同的值是不安全的。 為了使其安全,您可以使用互斥鎖序列化寫入。

嘗試:

var lock sync.Mutex
var a []string

lock.Lock()
a = append(a, s)
lock.Unlock()

有關互斥鎖如何工作的更多信息,請參閱教程和同步package

這是實現類似結果的模式,但不需要互斥體並且仍然是安全的。

package main

import (
    "fmt"
    "sync"
)

func main() {
    const sliceSize = 10000

    var wg = new(sync.WaitGroup)

    var a = make([]string, sliceSize)

    for i := 0; i < sliceSize; i++ {
        wg.Add(1)

        go func(s string, index int) {
            a[index] = s
            wg.Done()
        }("MaxPayne", i)
    }
    wg.Wait()
}

這與您的其他程序不完全相同,但這就是它的作用。

  1. 創建一個已經具有所需大小 10,000 的切片(此時每個元素都是一個空字符串)
  2. 對於每個數字 0...9999,創建一個新的 goroutine,該 goroutine 具有特定的索引以將特定的字符串寫入
  3. 在所有 goroutine 都退出並且 waitgroup 完成等待之后,我們就知道 slice 的每個索引都已成功填充。

即使沒有互斥體,memory 訪問現在也是安全的,因為每個 goroutine 只寫入其各自的索引(並且每個 goroutine 都有一個唯一的索引)。 因此,這些並發的 memory 寫入都不會相互沖突。 在最初創建具有所需大小的切片后,不需要再次分配變量a本身,因此消除了原始的 memory 競爭。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM