3 回答

TA貢獻1869條經驗 獲得超4個贊
用于取消,如鏈接文章中所示。close()
有問題的代碼不能保證工作。下面是它失敗的場景:
一個戈魯丁已準備好從 接收。所有其他戈魯丁人都在其他地方忙碌。
exit
main 發送的值由準備好的戈魯廷接收。
該戈魯廷向 接收的值發送一個值。
exit
main()
其他戈魯廷不會退出,因為沒有更多的值被發送到 。請參閱此使用時間的游樂場示例。滲漏以誘導問題場景。exit
為什么總是在go例程中進行接收,并且只有當所有例程都完成時,才會執行帶有注釋“//Final Exit”的通道接收?
該程序的執行方式就好像通道維護著一個有序的等待戈魯丁隊列,但規范中沒有任何內容可以保證該行為。即使通道具有有序隊列,如果 goroutine 正在執行某些操作而不是等待從 接收,則程序也可能會遇到上述情況。exit

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

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
如果這是一致的行為,那肯定是不可靠的。
請參閱在一個頻道上收聽多個戈魯丁,以獲取有關此內容的更多想法。
- 3 回答
- 0 關注
- 86 瀏覽
添加回答
舉報