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

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

Go - 如何知道輸出通道何時完成

Go - 如何知道輸出通道何時完成

Go
慕的地6264312 2021-09-10 14:53:05
我嘗試遵循 Rob Pike 在“并發(fā)不是并行”的演講中的例子,并做了這樣的事情:我正在啟動許多 go 例程作為從輸入通道讀取的工作人員,執(zhí)行一些處理,然后通過輸出通道發(fā)送結(jié)果.然后我開始另一個 go 例程,它從某個源讀取數(shù)據(jù)并通過他們的輸入通道將其發(fā)送給工作人員。最后,我想遍歷輸出通道中的所有結(jié)果并對其進行處理。問題是,由于工作在工作人員之間分配,我不知道所有工作人員何時完成,因此我可以停止向輸出通道詢問更多結(jié)果,并且我的程序可以正常結(jié)束。了解工作人員何時完成將結(jié)果發(fā)送到輸出通道的最佳做法是什么?
查看完整描述

3 回答

?
阿晨1998

TA貢獻2037條經(jīng)驗 獲得超6個贊

var Z = "Z"


func Loop() {

    sc := make(chan *string)

    ss := make([]string, 0)

    done := make(chan struct{}, 1)

    go func() {

        //1 QUERY

        slice1 := []string{"a", "b", "c"}

        //2 WG INIT

        var wg1 sync.WaitGroup

        wg1.Add(len(slice1))

        //3 LOOP->

        loopSlice1(slice1, sc, &wg1)

        //7 WG WAIT<-

        wg1.Wait()

        sc <- &Z

        done <- struct{}{}

    }()


    go func() {

        var cc *string

        for {

            cc = <-sc

            log.Infof("<-sc %s", *cc)

            if *cc == Z {

                break

            }

            ss = append(ss, *cc)

        }

    }()

    <-done

    log.Infof("FUN: %#v", ss)

}


func loopSlice1(slice1 []string, sc chan *string, wg1 *sync.WaitGroup) {

    for i, x := range slice1 {

        //4 GO

        go func(n int, v string) {

            //5 WG DONE

            defer wg1.Done()

            //6 DOING

            //[1 QUERY

            slice2 := []string{"X", "Y", "Z"}

            //[2 WG INIT

            var wg2 sync.WaitGroup

            wg2.Add(len(slice2))

            //[3 LOOP ->

            loopSlice2(n, v, slice2, sc, &wg2)

            //[7 WG WAIT <-

            wg2.Wait()

        }(i, x)

    }

}


func loopSlice2(n1 int, v1 string, slice2 []string, sc chan *string, wg2 *sync.WaitGroup) {

    for j, y := range slice2 {

        //[4 GO

        go func(n2 int, v2 string) {

            //[5 WG DONE

            defer wg2.Done()

            //[6 DOING

            r := fmt.Sprintf("%v%v %v,%v", n1, n2, v1, v2)

            sc <- &r

        }(j, y)

    }

}


查看完整回答
反對 回復(fù) 2021-09-10
?
不負相思意

TA貢獻1777條經(jīng)驗 獲得超10個贊

請我首先澄清您的術(shù)語:對渠道末端的誤解可能會導(dǎo)致以后出現(xiàn)問題。您詢問“輸出通道”和“輸入通道”。哪有這回事; 只有渠道。


每個通道都有兩端:輸出(寫入)端和輸入(讀取)端。我會假設(shè)這就是你的意思。


現(xiàn)在回答你的問題。


以最簡單的情況為例:您只有一個發(fā)送方 goroutine 寫入通道,并且只有一個工作 goroutine 從另一端讀取,并且通道的緩沖為零。發(fā)送方 goroutine 將在寫入每個項目時阻塞,直到該項目被消耗。通常,這在第一次發(fā)生時很快。一旦第一個項目傳遞給工作人員,工作人員就會很忙,發(fā)件人必須等待才能傳遞第二項內(nèi)容。因此,乒乓效應(yīng)如下:作者或讀者會忙,但不會兩者都忙。在 Rob Pike 所描述的意義上,goroutine 將是并發(fā)的,但實際上并不總是并行執(zhí)行。


如果您有許多從通道讀取的工作程序 goroutine(并且其輸入端由所有人共享),則發(fā)送方最初可以將一個項目分發(fā)給每個工作程序,但隨后必須等待它們工作(類似于上面描述的乒乓球案例)。最后,當(dāng)所有項目都由發(fā)送方發(fā)送后,它的工作就完成了。然而,讀者可能還沒有完成他們的工作。有時我們關(guān)心發(fā)件人是否提前完成,有時我們不關(guān)心。知道何時發(fā)生這種情況最容易通過 WaitGroup 完成(參見Not_a_Golfer的回答和我對相關(guān)問題的回答)。


還有一個稍微復(fù)雜一點的替代方法:您可以使用返回通道來完成信號傳輸,而不是使用WaitGroup. 這并不難做到,但WaitGroup在這種情況下是首選,更簡單。


相反,如果通道包含緩沖區(qū),則發(fā)送方發(fā)送最后一項的時間點會更快發(fā)生。在通道每個 worker 有一個緩沖區(qū)空間的極限情況下;這將允許發(fā)件人非常快速地完成,然后,可能繼續(xù)處理其他事情。(任何比這更多的緩沖都是浪費)。


發(fā)送者的這種解耦允許完全異步的行為模式,深受使用其他技術(shù)堆棧(Node-JS 和 JVM 的人)的人的喜愛。與它們不同的是,Go不需要您這樣做,但您可以選擇。


早在 90 年代初期,作為批量同步并行 (BSP) 策略工作的副作用,Leslie Valiant 證明有時非常簡單的同步策略可能很便宜。關(guān)鍵因素是需要足夠的并行松弛(也稱為過度并行)來保持處理器內(nèi)核忙碌。這意味著必須有足夠多的其他工作要做,以便任何特定的 goroutine 被阻塞一段時間都無關(guān)緊要。


奇怪的是,這可能意味著使用較少數(shù)量的 goroutine 可能比使用較大數(shù)量的 goroutine 需要更多的小心。


了解過度并行的影響是有用的:如果整個網(wǎng)絡(luò)具有過度并行,通常沒有必要付出額外的努力來使所有內(nèi)容異步,因為無論哪種方式,CPU 內(nèi)核都會很忙。


因此,雖然知道如何等待發(fā)件人完成很有用,但更大的應(yīng)用程序可能不需要您以同樣的方式關(guān)注。


作為最后一個腳注,WaitGroup是BSP 中使用的意義上的障礙。通過結(jié)合障礙和渠道,您可以同時使用 BSP 和 CSP。


查看完整回答
反對 回復(fù) 2021-09-10
?
aluckdog

TA貢獻1847條經(jīng)驗 獲得超7個贊

我個人喜歡為此使用 a sync.WaitGroup。等待組是一個同步計數(shù)器,它具有三種方法 - Wait()、Done()和Add()。您要做的是增加等待組的計數(shù)器,將其傳遞給工作人員,并讓Done()他們在完成后調(diào)用。然后,您只需阻塞另一端的等待組并在它們?nèi)客瓿珊箨P(guān)閉輸出通道,從而導(dǎo)致輸出處理器退出。


基本上:


// create the wait group

wg := sync.WaitGroup{}


// this is the output channel

outchan := make(chan whatever)


// start the workers

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

   wg.Add(1) //we increment by one the waitgroup's count


   //the worker pushes data onto the output channel and calls wg.Done() when done

   go work(&wg, outchan)

}


// this is our "waiter" - it blocks until all workers are done and closes the channel

go func() {

  wg.Wait()

  close(outchan)

}()


//this loop will exit automatically when outchan is closed

for item := range outchan {

   workWithIt(item)

}


// TADA!


查看完整回答
反對 回復(fù) 2021-09-10
  • 3 回答
  • 0 關(guān)注
  • 182 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

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

公眾號

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