亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

與 for 循環和匿名函數的并發行為異常

與 for 循環和匿名函數的并發行為異常

Go
料青山看我應如是 2022-01-04 21:21:19
我已經找到了一種讓代碼按照我想要的方式運行的方法,但我想了解它為什么會這樣,以便我對 Go 并發性的理解有所提高。我正在測試sync.WaitGroup等待一些 goroutine 完成,因為我計劃以這種方式多次上傳到 Amazon S3。這是我最初的代碼:func main() {    var wg sync.WaitGroup    for i := 1; i <= 5; i++ {        wg.Add(1)        go func() {            fmt.Println(i)            time.Sleep(time.Second * 1)            wg.Done()        }()    }    wg.Wait()}我很驚訝地看到輸出是:6, 6, 6, 6, 6。而不是像:2, 4, 1, 5, 3。由于循環甚至沒有達到 6,這對我來說毫無意義。后來我將該i變量作為參數傳遞給匿名函數,然后它的行為符合我的預期。為什么會發生這種情況?我不明白。
查看完整描述

2 回答

?
拉丁的傳說

TA貢獻1789條經驗 獲得超8個贊

在這種情況下,在 for 循環完成之前,不會調度任何 goroutine。為了使 for 循環中斷,i必須不小于或等于 5,因此在該點為 6。當 goroutine 運行時,它們每個都會打印i在閉包中捕獲的單個變量的值。

當您將i參數作為參數傳遞給函數時,您將當前值復制到一個新變量中,并捕獲當時的值。


查看完整回答
反對 回復 2022-01-04
?
慕俠2389804

TA貢獻1719條經驗 獲得超6個贊

要回答您的問題,您必須傳入i您的,func以便每個例程都有自己的i.


所以你的代碼應該是這樣的


func main() {

    var wg sync.WaitGroup


    for i := 1; i <= 5; i++ {

        wg.Add(1)

        go func(i int) {

            fmt.Println(i)

            time.Sleep(time.Second * 1)

            wg.Done()

        }(i)

    }


    wg.Wait()

}

我編寫了這個實用程序函數來幫助并行化一組函數:


import "sync"


// Parallelize parallelizes the function calls

func Parallelize(functions ...func()) {

    var waitGroup sync.WaitGroup

    waitGroup.Add(len(functions))


    defer waitGroup.Wait()


    for _, function := range functions {

        go func(copy func()) {

            defer waitGroup.Done()

            copy()

        }(function)

    }

}

所以在你的情況下,我們可以這樣做


func main() {

    functions := []func(){}

    for i := 1; i <= 5; i++ {

            function := func(i int) func() {

                return func() {

                        fmt.Println(i)

                }

            }(i)


        functions = append(functions, function)

    }


    Parallelize(functions...)


    fmt.Println("Done")

}

如果你想使用 Parallelize 功能,你可以在這里找到它https://github.com/shomali11/util


查看完整回答
反對 回復 2022-01-04
  • 2 回答
  • 0 關注
  • 173 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號