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

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

sync.WaitGroup 在 Channels 上的優(yōu)勢(shì)是什么?

sync.WaitGroup 在 Channels 上的優(yōu)勢(shì)是什么?

Go
慕運(yùn)維8079593 2021-12-27 10:34:27
我正在開(kāi)發(fā)一個(gè)并發(fā) Go 庫(kù),我偶然發(fā)現(xiàn)了 goroutines 之間的兩種不同的同步模式,它們的結(jié)果相似:package mainimport (    "fmt"    "sync"    "time")var wg sync.WaitGroupfunc main() {    words := []string{"foo", "bar", "baz"}    for _, word := range words {        wg.Add(1)        go func(word string) {            time.Sleep(1 * time.Second)            defer wg.Done()            fmt.Println(word)        }(word)    }    // do concurrent things here    // blocks/waits for waitgroup    wg.Wait()}package mainimport (    "fmt"    "time")func main() {    words := []string{"foo", "bar", "baz"}    done := make(chan bool)    // defer close(done)    for _, word := range words {        // fmt.Println(len(done), cap(done))        go func(word string) {            time.Sleep(1 * time.Second)            fmt.Println(word)            done <- true        }(word)    }    // Do concurrent things here    // This blocks and waits for signal from channel    for range words {        <-done    }}我被告知它的sync.WaitGroup性能稍好一些,而且我已經(jīng)看到它被普遍使用。但是,我發(fā)現(xiàn)頻道更慣用。使用sync.WaitGroupover channel的真正優(yōu)勢(shì)是什么和/或當(dāng)它更好時(shí)可能會(huì)是什么情況?
查看完整描述

3 回答

?
慕標(biāo)5832272

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

獨(dú)立于第二個(gè)示例的正確性(如評(píng)論中所述,您沒(méi)有按照自己的想法行事,但很容易修復(fù)),我傾向于認(rèn)為第一個(gè)示例更容易掌握。

現(xiàn)在,我什至不會(huì)說(shuō)頻道更慣用了。通道是 Go 語(yǔ)言的一個(gè)標(biāo)志性特性,并不意味著盡可能地使用它們是慣用的。Go 中的慣用語(yǔ)是使用最簡(jiǎn)單、最容易理解的解決方案:在這里,WaitGroup傳遞含義(您的主要功能是Wait讓工人完成)和機(jī)制(工人通知他們何時(shí)完成Done)。

除非您處于非常特殊的情況,否則我不建議在此處使用通道解決方案。


查看完整回答
反對(duì) 回復(fù) 2021-12-27
?
楊魅力

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

這取決于用例。如果您要分派一次性作業(yè)以并行運(yùn)行而無(wú)需知道每個(gè)作業(yè)的結(jié)果,那么您可以使用WaitGroup. 但是如果你需要從 goroutines 收集結(jié)果,那么你應(yīng)該使用一個(gè)通道。

由于通道雙向工作,我?guī)缀蹩偸鞘褂猛ǖ馈?/p>

另一方面,正如評(píng)論中所指出的,您的頻道示例未正確實(shí)現(xiàn)。您需要一個(gè)單獨(dú)的通道來(lái)指示沒(méi)有更多的工作要做(一個(gè)例子是這里)。在您的情況下,由于您事先知道字?jǐn)?shù),因此您可以只使用一個(gè)緩沖通道并接收固定次數(shù)以避免聲明關(guān)閉通道。


查看完整回答
反對(duì) 回復(fù) 2021-12-27
?
ABOUTYOU

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

對(duì)于您的簡(jiǎn)單示例(表示作業(yè)完成),這WaitGroup是顯而易見(jiàn)的選擇。Go 編譯器非常友好,不會(huì)怪你使用通道來(lái)發(fā)送簡(jiǎn)單的完成任務(wù)信號(hào),但一些代碼審查者會(huì)這樣做。


"WaitGroup 等待一組 goroutines 完成。主 goroutine 調(diào)用Add(n)設(shè)置要等待的 goroutines 的數(shù)量。然后每個(gè) goroutines 運(yùn)行并Done()在完成時(shí)調(diào)用。同時(shí),Wait 可用于阻塞直到所有g(shù)oroutine 已經(jīng)完成了?!?/p>

words := []string{"foo", "bar", "baz"}

var wg sync.WaitGroup

for _, word := range words {

    wg.Add(1)

    go func(word string) {

        defer wg.Done()

        time.Sleep(100 * time.Millisecond) // a job

        fmt.Println(word)

    }(word)

}

wg.Wait()

可能性僅受您的想象力的限制:


通道可以被緩沖:

words := []string{"foo", "bar", "baz"}

done := make(chan struct{}, len(words))

for _, word := range words {

    go func(word string) {

        time.Sleep(100 * time.Millisecond) // a job

        fmt.Println(word)

        done <- struct{}{} // not blocking

    }(word)

}

for range words {

    <-done

}

通道可以是無(wú)緩沖的,你可以只使用一個(gè)信號(hào)通道(例如chan struct{}):

words := []string{"foo", "bar", "baz"}

done := make(chan struct{})

for _, word := range words {

    go func(word string) {

        time.Sleep(100 * time.Millisecond) // a job

        fmt.Println(word)

        done <- struct{}{} // blocking

    }(word)

}

for range words {

    <-done

}

您可以限制具有緩沖通道容量的并發(fā)作業(yè)數(shù):

t0 := time.Now()

var wg sync.WaitGroup

words := []string{"foo", "bar", "baz"}

done := make(chan struct{}, 1) // set the number of concurrent job here

for _, word := range words {

    wg.Add(1)

    go func(word string) {

        done <- struct{}{}

        time.Sleep(100 * time.Millisecond) // job

        fmt.Println(word, time.Since(t0))

        <-done

        wg.Done()

    }(word)

}

wg.Wait()

您可以使用頻道發(fā)送消息:

done := make(chan string)

go func() {

    for _, word := range []string{"foo", "bar", "baz"} {

        done <- word

    }

    close(done)

}()

for word := range done {

    fmt.Println(word)

}

基準(zhǔn):


    go test -benchmem -bench . -args -n 0

# BenchmarkEvenWaitgroup-8  1827517   652 ns/op    0 B/op  0 allocs/op

# BenchmarkEvenChannel-8    1000000  2373 ns/op  520 B/op  1 allocs/op

    go test -benchmem -bench .

# BenchmarkEvenWaitgroup-8  1770260   678 ns/op    0 B/op  0 allocs/op

# BenchmarkEvenChannel-8    1560124  1249 ns/op  158 B/op  0 allocs/op

代碼( main_test.go):


package main


import (

    "flag"

    "fmt"

    "os"

    "sync"

    "testing"

)


func BenchmarkEvenWaitgroup(b *testing.B) {

    evenWaitgroup(b.N)

}

func BenchmarkEvenChannel(b *testing.B) {

    evenChannel(b.N)

}

func evenWaitgroup(n int) {

    if n%2 == 1 { // make it even:

        n++

    }

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

        wg.Add(1)

        go func(n int) {

            select {

            case ch <- n: // tx if channel is empty

            case i := <-ch: // rx if channel is not empty

                // fmt.Println(n, i)

                _ = i

            }

            wg.Done()

        }(i)

    }

    wg.Wait()

}

func evenChannel(n int) {

    if n%2 == 1 { // make it even:

        n++

    }

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

        go func(n int) {

            select {

            case ch <- n: // tx if channel is empty

            case i := <-ch: // rx if channel is not empty

                // fmt.Println(n, i)

                _ = i

            }

            done <- struct{}{}

        }(i)

    }

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

        <-done

    }

}

func TestMain(m *testing.M) {

    var n int // We use TestMain to set up the done channel.

    flag.IntVar(&n, "n", 1_000_000, "chan cap")

    flag.Parse()

    done = make(chan struct{}, n)

    fmt.Println("n=", n)

    os.Exit(m.Run())

}


var (

    done chan struct{}

    ch   = make(chan int)

    wg   sync.WaitGroup

)


查看完整回答
反對(duì) 回復(fù) 2021-12-27
  • 3 回答
  • 0 關(guān)注
  • 246 瀏覽
慕課專欄
更多

添加回答

舉報(bào)

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號(hào)

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