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

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

Go 頻道不適用于生產(chǎn)者/消費者樣本

Go 頻道不適用于生產(chǎn)者/消費者樣本

Go
慕斯王 2023-06-01 18:18:21
我剛剛在 Mac 上安裝了 Go,這是代碼package mainimport (    "fmt"    "time")func Product(ch chan<- int) {    for i := 0; i < 100; i++ {        fmt.Println("Product:", i)        ch <- i    }}func Consumer(ch <-chan int) {    for i := 0; i < 100; i++ {        a := <-ch        fmt.Println("Consmuer:", a)    }}func main() {    ch := make(chan int, 1)    go Product(ch)    go Consumer(ch)    time.Sleep(500)}我“去運行 producer_consumer.go”,屏幕上沒有輸出,然后退出。我的程序有問題嗎?如何解決?
查看完整描述

3 回答

?
開心每一天1111

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

這是一個相當(dāng)冗長的答案,但簡單地說:

  • 過去time.Sleep一直等到希望其他例程完成他們的工作是不好的。

  • 除了他們通過渠道交換的類型之外,消費者和生產(chǎn)者不應(yīng)該知道彼此的任何信息。您的代碼依賴于消費者和生產(chǎn)者都知道將傳遞多少整數(shù)。不是一個現(xiàn)實的場景

  • 通道可以迭代(將它們視為線程安全的共享切片)

  • 通道應(yīng)該關(guān)閉

在這個相當(dāng)冗長的答案的底部,我試圖解釋一些基本概念和最佳實踐(好吧,更好的實踐),你會發(fā)現(xiàn)你的代碼被重寫以工作顯示所有值而不依賴于time.Sleep. 我沒有測試該代碼,但應(yīng)該沒問題


是的,這里有幾個問題。就像一個項目符號列表:

  1. 你的通道被緩沖到 1,這很好,但沒有必要

  2. 你的頻道從未關(guān)閉

  3. 您正在等待 500ns,然后退出,無論例程是否已完成,甚至是否已開始處理該問題。

  4. 沒有對例程的集中控制,一旦你啟動它們,你就沒有控制權(quán)。如果您按下 ctrl+c,您可能希望在編寫處理重要數(shù)據(jù)的代碼時取消例程。檢查信號處理和上下文

通道緩沖器

鑒于您已經(jīng)知道要將多少價值推送到您的頻道,為什么不簡單地創(chuàng)造呢ch := make(chan int, 100)?這樣,無論消費者做什么,您的發(fā)布者都可以繼續(xù)將消息推送到頻道。

您不需要這樣做,但是根據(jù)您要執(zhí)行的操作向您的頻道添加一個合理的緩沖區(qū)絕對值得一試。不過目前,這兩個例程都在使用fmt.Println& co,這將成為任何一種方式的瓶頸。打印到 STDOUT 是線程安全的,并且是緩沖的。這意味著每次調(diào)用fmt.Print*都會獲得一個鎖,以避免來自兩個例程的文本被合并。

關(guān)閉通道

您可以簡單地將所有值推送到您的頻道,然后關(guān)閉它。然而,這是一種糟糕的形式。WRT 通道的經(jīng)驗法則是通道是在同一個例程中創(chuàng)建和關(guān)閉的。意思是:你正在主例程中創(chuàng)建通道,那是它應(yīng)該關(guān)閉的地方。

您需要一種機制來同步,或者至少密切關(guān)注您的例程是否已完成其工作。這是使用sync包或通過第二個渠道完成的。

// using a done channel

func produce(ch chan<- int) <-chan struct{} {

    done := make(chan struct{})

    go func() {

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

            ch <- i

        }

        // all values have been published

        // close done channel

        close(done)

    }()

    return done

}


func main() {

    ch := make(chan int, 1)

    done := produce(ch)

    go consume(ch)

    <-done // if producer has done its thing

    close(ch) // we can close the channel

}


func consume(ch <-chan int) {

    // we can now simply loop over the channel until it's closed

    for i := range ch {

        fmt.Printf("Consumed %d\n", i)

    }

}

好的,但是在這里您仍然需要等待consume例程完成。


您可能已經(jīng)注意到,done通道在技術(shù)上并沒有在創(chuàng)建它的同一個例程中關(guān)閉。但是,因為例程被定義為閉包,所以這是一個可以接受的折衷方案?,F(xiàn)在讓我們看看如何使用等待組:


import (

    "fmt"

    "sync"

)


func product(wg *sync.WaitGroup, ch chan<- int) {

    defer wg.Done() // signal we've done our job

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

        ch <- i

    }

}


func main() {

    ch := make(chan int, 1)

    wg := sync.WaitGroup{}

    wg.Add(1) // I'm adding a routine to the channel

    go produce(&wg, ch)

    wg.Wait() // will return once `produce` has finished

    close(ch)

}

好的,這看起來很有希望,我可以讓例程告訴我它們何時完成任務(wù)。但是,如果我將消費者和生產(chǎn)者都添加到等待組,我就不能簡單地遍歷通道。只有當(dāng)兩個例程都調(diào)用時,通道才會關(guān)閉wg.Done(),但如果消費者卡在一個永遠不會關(guān)閉的通道上循環(huán),那么我就創(chuàng)建了一個死鎖。


解決方案:

此時混合將是最簡單的解決方案:將消費者添加到等待組,并使用生產(chǎn)者中的完成通道來獲取:


func produce(ch chan<- int) <-chan struct{} {

    done := make(chan struct{})

    go func() {

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

            ch <- i

        }

        close(done)

    }()

    return done

}


func consume(wg *sync.WaitGroup, ch <-chan int) {

    defer wg.Done()

    for i := range ch {

        fmt.Printf("Consumer: %d\n", i)

    }

}


func main() {

    ch := make(chan int, 1)

    wg := sync.WaitGroup{}

    done := produce(ch)

    wg.Add(1)

    go consume(&wg, ch)

    <- done // produce done

    close(ch)

    wg.Wait()

    // consumer done

    fmt.Println("All done, exit")

}


查看完整回答
反對 回復(fù) 2023-06-01
?
慕田峪9158850

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

我稍微改變了(延長時間。睡眠)你的代碼。在我的 Linux x86_64 上運行良好


func Product(ch chan<- int) {

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

        fmt.Println("Product:", i)

        ch <- i

    }

}

func Consumer(ch <-chan int) {

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

        a := <-ch

        fmt.Println("Consmuer:", a)

    }

}

func main() {

    ch := make(chan int, 1)

    go Product(ch)

    go Consumer(ch)

    time.Sleep(10000)

}

輸出 go run s1.go


Product: 0

Product: 1

Product: 2


查看完整回答
反對 回復(fù) 2023-06-01
?
交互式愛情

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

time.Sleep需要一個time.Duration,而不是一個整數(shù)。godoc顯示了如何正確調(diào)用它的示例。在你的情況下,你可能想要:

time.Sleep(500?*?time.Millisecond)

您的程序快速退出(但沒有給您錯誤)的原因是由于(有點令人驚訝)的time.Duration實施方式。

time.Duration只是 的類型別名int64。在內(nèi)部,它使用該值來表示以納秒為單位的持續(xù)時間。當(dāng)您調(diào)用 時time.Sleep(500),編譯器會很樂意將數(shù)字文字解釋500time.Duration.?不幸的是,這意味著 500 ns。

time.Millisecond是一個常數(shù),等于毫秒中的納秒數(shù) (1,000,000)。好處是,要求您顯式地進行乘法運算會使調(diào)用者清楚地知道該參數(shù)的單位是什么。不幸的是,time.Sleep(500)這是完全有效的 go 代碼,但沒有達到大多數(shù)初學(xué)者的預(yù)期。


查看完整回答
反對 回復(fù) 2023-06-01
  • 3 回答
  • 0 關(guān)注
  • 160 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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