第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

Goroutines 節(jié)流示例

Goroutines 節(jié)流示例

Go
慕慕森 2022-06-01 17:50:13
我正在通過(guò) Udemy 課程學(xué)習(xí)基本的圍棋。在 goroutines 部分,有一個(gè)節(jié)流的例子,它讓我理解了等待組是如何工作的。package mainimport (    "fmt"    "math/rand"    "sync"    "time")func main() {    c1 := make(chan int)    c2 := make(chan int)    go populate(c1)    go fanOutIn(c1, c2)    for v := range c2 {        fmt.Println(v)    }    fmt.Println("about to exit")}func populate(c chan int) {    for i := 0; i < 100; i++ {        c <- i    }    close(c)}func fanOutIn(c1, c2 chan int) {    var wg sync.WaitGroup    const goroutines = 10    wg.Add(goroutines)     for i := 0; i < goroutines; i++ {        go func() {            for v := range c1 {                func(v2 int) {                    c2 <- timeConsumingWork(v2)                }(v)            }            wg.Done()        }()    }    wg.Wait()    close(c2)}func timeConsumingWork(n int) int {    time.Sleep(time.Microsecond * time.Duration(rand.Intn(500)))    return n + rand.Intn(1000)}不符合我理解的部分是在fanOutIn我們?cè)O(shè)置WaitGroup, 和Add(10).為什么我打印出 100 個(gè)值?只能將單個(gè)值 ( i := 0) 放入c1,并且該值永遠(yuǎn)不會(huì)從通道中顯式刪除。然后代碼命中wg.Done(),等待組隊(duì)列減少到 9,依此類(lèi)推。根據(jù)我目前的理解,我希望看到 10 個(gè)值0 + rand.Intn(1000)。
查看完整描述

1 回答

?
一只甜甜圈

TA貢獻(xiàn)1836條經(jīng)驗(yàn) 獲得超5個(gè)贊

分拆出來(lái)的函數(shù)如下所示(包括go前面的 和調(diào)用它的括號(hào)):


go func() {

    for v := range c1 {

        func(v2 int) {

            c2 <- timeConsumingWork(v2)

        }(v)

    }

    wg.Done()

}()

這段代碼有點(diǎn)奇怪和離奇。讓我們進(jìn)一步縮小它,丟棄wg.Done并只保留for循環(huán)本身:


for v := range c1 {

    func(v2 int) {

        c2 <- timeConsumingWork(v2)

    }(v)

}

有一個(gè)內(nèi)部未命名的函數(shù)在這里非常沒(méi)用;我們可以在不改變程序行為的情況下丟棄它,得到:


for v := range c1 {

    c2 <- timeConsumingWork(v)

}

這最后是一個(gè)簡(jiǎn)單的循環(huán)?,F(xiàn)在的一個(gè)關(guān)鍵問(wèn)題是:您期望從這個(gè)循環(huán)中進(jìn)行多少次迭代? 注意:它不一定是任何常數(shù)。或許更好的方式來(lái)表達(dá)這個(gè)問(wèn)題是:這個(gè)循環(huán)什么時(shí)候結(jié)束?


for循環(huán)讀取一個(gè)通道。這種循環(huán)在從通道讀取指示沒(méi)有更多數(shù)據(jù)時(shí)結(jié)束,即通道已關(guān)閉且其隊(duì)列為空。(請(qǐng)參閱循環(huán)的 Go 規(guī)范部分for。)


所以這個(gè)最里面的循環(huán),for v := range c1直到通道c1關(guān)閉并且隊(duì)列中沒(méi)有更多數(shù)據(jù)時(shí)才會(huì)終止。該頻道是使用以下內(nèi)容創(chuàng)建的:


c1 := make(chan int)

所以它沒(méi)有隊(duì)列,所以我們甚至不需要考慮這一點(diǎn):它在 aclose(c1)關(guān)閉它后終止。 您現(xiàn)在應(yīng)該尋找一個(gè)closecloses c1。


我們的近在哪里?

這是關(guān)閉的地方c1:


func populate(c chan int) {

    for i := 0; i < 100; i++ {

        c <- i

    }

    close(c)

}

我們稱(chēng)之為 withc1作為它的參數(shù),所以它的 final close(c)closes c1。現(xiàn)在你可以問(wèn):我們什么時(shí)候接到這個(gè)close電話? 答案很明顯:i >= 100在循環(huán)之后,即,在我們將 100 個(gè)值(分別從 0 到 99)發(fā)送到 channel 之后c1。


什么fanOutIn是剝離 10 個(gè) goroutine。10 個(gè) goroutine 中的每一個(gè)都運(yùn)行我上面引用的第一個(gè)匿名函數(shù)。該匿名函數(shù)有一個(gè)循環(huán),運(yùn)行次數(shù)不定,一直重復(fù)直到通道c1關(guān)閉。循環(huán)中的每次行程都會(huì)獲取通道的值,因此最初,如果十個(gè) goroutine 都設(shè)法在有任何可用值之前啟動(dòng),那么所有十個(gè) goroutine 都將等待值。


當(dāng)生產(chǎn)者函數(shù)將一個(gè)值放入通道時(shí),十個(gè)等待的 goroutine 中的一個(gè)將獲取它并開(kāi)始使用它。如果該 goroutine 需要很長(zhǎng)時(shí)間才能回到自己for循環(huán)的頂部,則另一個(gè) goroutine 將獲取下一個(gè)生成的值。所以這里發(fā)生的情況是,多達(dá) 10 個(gè)生成的值通過(guò)通道傳播到多達(dá) 10 個(gè) goroutine。1 這些(最多 10 個(gè))goroutine 中的每一個(gè)都花費(fèi)了一些重要的時(shí)間來(lái)使用它的值,然后將最終產(chǎn)品值發(fā)送到通道c2并返回到它自己的無(wú)限for循環(huán)的頂部。


只有當(dāng)生產(chǎn)者關(guān)閉了它的通道c(這里是我們的c1)時(shí),十個(gè) goroutine 才會(huì)看到一個(gè)關(guān)閉的通道空隊(duì)列,從而允許它們退出for循環(huán)。當(dāng)他們退出他們的for循環(huán)時(shí),他們每個(gè)人都會(huì)調(diào)用wg.Done()(一次)并終止。


因此,一旦close(c1)發(fā)生(通過(guò)close(c)in populate),最終所有十個(gè)匿名 goroutine 都將調(diào)用wg.Done(). 屆時(shí),wg.Wait()infanOutIn將返回。這將調(diào)用close(c2)并從 中返回fanOutIn,同時(shí)終止該goroutine。


同時(shí),在 中main,我們使用for v := range c2從通道中讀取c2。當(dāng)十個(gè) goroutine 中的任何一個(gè)for寫(xiě)入值時(shí),此循環(huán)將運(yùn)行。c2只有當(dāng)它自己關(guān)閉時(shí)它才會(huì)退出c2(它的隊(duì)列也必須是空的,但又c2是一個(gè)零長(zhǎng)度隊(duì)列)。所以在關(guān)閉之前main不會(huì)繼續(xù)通過(guò)for循環(huán),直到返回才會(huì)發(fā)生,直到發(fā)生十次調(diào)用才會(huì)發(fā)生,直到通道關(guān)閉才會(huì)發(fā)生。c2wg.Wait()wg.Done()c1


這意味著在調(diào)用之前main無(wú)法通過(guò)自己的for循環(huán),并且只有在生成恰好 100 個(gè)值之后才會(huì)發(fā)生這種情況。populateclose(c)


查看完整回答
反對(duì) 回復(fù) 2022-06-01
  • 1 回答
  • 0 關(guān)注
  • 152 瀏覽
慕課專(zhuān)欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號(hào)