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

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

Go - 為什么調(diào)度 goroutine 后臺工作人員也需要自己的 goroutine?

Go - 為什么調(diào)度 goroutine 后臺工作人員也需要自己的 goroutine?

Go
哈士奇WWW 2021-07-28 20:18:13
我正在研究 Go 的一些并發(fā)模式。我查看了使用 goroutine 和輸入/輸出通道來實(shí)現(xiàn)后臺工作者,并注意到當(dāng)我將新作業(yè)發(fā)送到接收通道(基本上是將新作業(yè)排隊(duì))時,我必須在 goroutine 中執(zhí)行它,否則調(diào)度會被搞砸。意義:這會崩潰:for _, jobData := range(dataSet) {    input <- jobData}這有效:go func() {    for _, jobData := range(dataSet) {        input <- jobData    }}()對于更具體的事情,我玩了一些無意義的代碼(這里是在 go playground 中):package mainimport (    "log"    "runtime")func doWork(data int) (result int) {    // ... some 'heavy' computation    result = data * data    return}// do the processing of the input and return// results on the output channelfunc Worker(input, output chan int) {    for data := range input {        output <- doWork(data)    }}func ScheduleWorkers() {    input, output := make(chan int), make(chan int)    for i := 0 ; i < runtime.NumCPU() ; i++ {        go Worker(input, output)    }    numJobs := 20    // THIS DOESN'T WORK    // and crashes the program    /*    for i := 0 ; i < numJobs ; i++ {        input <- i    }    */    // THIS DOES    go func() {        for i := 0 ; i < numJobs ; i++ {            input <- i        }    }()    results := []int{}    for i := 0 ; i < numJobs ; i++ {        // read off results        result := <-output        results = append(results, result)        // do stuff...    }    log.Printf("Result: %#v\n", results)}func main() {    ScheduleWorkers()}我正在努力解決這個微妙的差異 - 感謝您的幫助。謝謝。
查看完整描述

3 回答

?
智慧大石

TA貢獻(xiàn)1946條經(jīng)驗(yàn) 獲得超3個贊

您的ScheduleWorks函數(shù)在主協(xié)程(即運(yùn)行該main()函數(shù)的協(xié)程,程序在該協(xié)程中啟動)中通過input. AWorker接收它,并通過 發(fā)送另一個值output。但是此時沒有人接收output,因此程序無法繼續(xù),主 goroutine 將下一個值發(fā)送到另一個Worker.

對每個 Worker 重復(fù)這個推理。你有runtime.NumCPU()工人,這可能少于numJobs. 比方說runtime.NumCPU() == 4,所以你有 4 個工人。最后,您已成功發(fā)送 4 個值,每個值都是一對一的Worker。由于沒有人從 讀取output,所有 Worker 都忙于嘗試發(fā)送,因此它們無法通過 接受更多數(shù)據(jù)input,因此第五個input <- i將掛起。此時每個 goroutine 都在等待;這就是僵局。


http://img1.sycdn.imooc.com//6107a234000154b405730256.jpg

您會注意到,如果您啟動 20 個或更多的 Worker 而不是 runtime.NumCPU(),則該程序可以運(yùn)行。那是因?yàn)橹?goroutine 可以通過 發(fā)送它想要的所有內(nèi)容input,因?yàn)橛凶銐虻墓ぷ魅藛T來接收它們。

如果不是所有這些,而是將input <- i循環(huán)放在另一個 goroutine 中,就像在您成功的示例中一樣,maingoroutine(在其中ScheduleWorks運(yùn)行)可以繼續(xù)并從output. 所以,每次這個新的 goroutine 發(fā)送一個值時,worker 發(fā)送另一個值,output主 goroutine 得到這個輸出,worker 可以接收另一個值。沒有人等待,程序成功了。

http://img1.sycdn.imooc.com//6107a24400013af105760254.jpg

查看完整回答
反對 回復(fù) 2021-08-02
?
有只小跳蛙

TA貢獻(xiàn)1824條經(jīng)驗(yàn) 獲得超8個贊

這是因?yàn)?Go 中的所有內(nèi)容默認(rèn)都是阻塞的。

當(dāng)您在無緩沖通道上發(fā)送第一個值時,它會阻塞,直到接收器從通道中取出該值。

可以通過添加“容量”來緩沖通道。

例如:

make(chan int, 20) // Make a buffered channel of int with capacity 20

Go 規(guī)范

容量(以元素數(shù)為單位)設(shè)置通道中緩沖區(qū)的大小。如果容量大于零,則通道是異步的:如果緩沖區(qū)未滿(發(fā)送)或非空(接收),則通信操作成功而不會阻塞,并且元素按發(fā)送順序接收。如果容量為零或不存在,則只有當(dāng)發(fā)送方和接收方都準(zhǔn)備好時,通信才能成功。

您可以通過使用緩沖通道而不是非緩沖通道來使原始函數(shù)工作,但是將函數(shù)調(diào)用包裝在 goroutine 中可能是更好的方法,因?yàn)樗鼘?shí)際上是并發(fā)的。

來自Effective Go(完整閱讀此文檔!它可能是 Stack Overflow 上 Go 答案中鏈接最多的文檔):

接收器總是阻塞直到有數(shù)據(jù)要接收。如果通道未緩沖,則發(fā)送方將阻塞,直到接收方收到該值。如果通道有緩沖區(qū),則發(fā)送方只會阻塞,直到值被復(fù)制到緩沖區(qū);如果緩沖區(qū)已滿,這意味著等待某個接收器檢索到一個值。

如果您使用緩沖通道,那么您只是填充通道,繼續(xù)前進(jìn),然后再次排空。不能同時進(jìn)行。

例子:

改變

input, output := make(chan int), make(chan int)

input, output := make(chan int, 20), make(chan int, 20)


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

添加回答

舉報

0/150
提交
取消
微信客服

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

幫助反饋 APP下載

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

公眾號

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