亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

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

退出在無緩沖通道上等待的多個 go 例程

退出在無緩沖通道上等待的多個 go 例程

Go
泛舟湖上清波郎朗 2022-10-04 19:31:56
我試圖同時退出多個戈魯廷。根據 https://www.godesignpatterns.com/2014/04/exiting-multiple-goroutines-simultaneously.html 有一個明確的方法來做到這一點。我看到的另一種方法是以下package mainimport (    "fmt"    "time")func main() {    var inCh chan int = make(chan int, 100)    var exit chan bool = make(chan bool)    for i := 0; i < 20; i++ {        go func(instance int) {            fmt.Println("In go routine ", instance)            for {                select {                case <-exit:                    fmt.Println("Exit received from ", instance)                    exit <- true                    return                case value := <-inCh:                    fmt.Println("Value=", value)                }            }        }(i)    }    time.Sleep(1 * time.Second)    exit <- true    <-exit   // Final exit    fmt.Println("Final exit")}但是我很困惑,我真的不明白為什么最后的無緩沖通道被執行為最后一個語句。實際上,我有20個go例程在聽出口頻道。隨機一個人將收到它并將其發送給另一個人。為什么總是在go例程中進行接收,并且只有當所有例程都完成時,才會執行帶有注釋“//Final Exit”的通道接收?如果有人能給我一個解釋,我將不勝感激。
查看完整描述

3 回答

?
MMTTMM

TA貢獻1869條經驗 獲得超4個贊

用于取消,如鏈接文章中所示。close()

有問題的代碼不能保證工作。下面是它失敗的場景:

  1. 一個戈魯丁已準備好從 接收。所有其他戈魯丁人都在其他地方忙碌。exit

  2. main 發送的值由準備好的戈魯廷接收。

  3. 該戈魯廷向 接收的值發送一個值。exitmain()

其他戈魯廷不會退出,因為沒有更多的值被發送到 。請參閱此使用時間的游樂場示例。滲漏以誘導問題場景。exit

為什么總是在go例程中進行接收,并且只有當所有例程都完成時,才會執行帶有注釋“//Final Exit”的通道接收?

該程序的執行方式就好像通道維護著一個有序的等待戈魯丁隊列,但規范中沒有任何內容可以保證該行為。即使通道具有有序隊列,如果 goroutine 正在執行某些操作而不是等待從 接收,則程序也可能會遇到上述情況。exit


查看完整回答
反對 回復 2022-10-04
?
qq_笑_17

TA貢獻1818條經驗 獲得超7個贊

如果您注意到程序的輸出


In go routine  6

In go routine  0

In go routine  7

.

.

Exit received from  6

Exit received from  0

Exit received from  7

.

.

Final exit

它們以相同(或幾乎相同)的順序被調用,這些順序與它們的啟動方式相同。如果您的 Go 例程都不繁忙,則將使用第一個注冊的例程。這只是運行時的實現,我不會指望這種行為。


您的最終出口是最后一個要收聽的通道,因此最后使用它。


如果刪除時間。循環后睡覺,您的最終出口幾乎會立即被調用,并且您的大多數go例程都不會收到退出信號


輸出與時間輸出。睡眠(在跑步之間會非常多)


In go routine  0

Exit received from  0

In go routine  1

In go routine  2

In go routine  3

In go routine  4

In go routine  5

In go routine  6

In go routine  7

In go routine  14

In go routine  15

In go routine  16

In go routine  17

In go routine  18

In go routine  19

Final exit


查看完整回答
反對 回復 2022-10-04
?
四季花海

TA貢獻1811條經驗 獲得超5個贊

請考慮此輕微修改。


package main


import (

    "fmt"

)


func main() {

    var exit chan int = make(chan int)

        var workers = 20

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

        go func(instance int) {

            fmt.Println("In go routine ", instance)

            for {

                select {

                case i := <-exit:

                    fmt.Println("Exit", i, "received from ", instance)

                    exit <- i-1

                    return

                }

            }

        }(i)

    }

    exit <- workers

    fmt.Println("Final exit:", <-exit)

}

在這里,我做了3件事:首先,為了簡潔起見,我刪除了未使用的頻道。其次,我消除了睡眠。第三,我將通道更改為每次通過都會遞減的通道。如果我傳入工作人員的數量,則除“最終”消息以外的任何值都表示工作人員被丟棄。exitint0


下面是一個運行示例:


% go run t.go

In go routine  8

In go routine  5

In go routine  0

In go routine  2

Exit 20 received from  8

Exit 19 received from  5

Final exit: 18

In go routine  13

當呼叫時,直到睡眠結束才會安排。其他哥魯丁都有這個時間來設置他們的頻道閱讀器。我只能假設,因為我在任何地方都找不到它,頻道讀者很可能在大致的時間順序錯誤中排隊 - 因此,保證讀者是最后一個。maintime.Sleepsleepmain


如果這是一致的行為,那肯定是不可靠的。


請參閱在一個頻道上收聽多個戈魯丁,以獲取有關此內容的更多想法。


查看完整回答
反對 回復 2022-10-04
  • 3 回答
  • 0 關注
  • 86 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號