理解 Goroutine 執行順序
在基於 goroutine 的程式中,goroutine 的執行順序可能是不可預測的。這是因為 goroutine 是並發執行的,並且無法保證它們何時或以什麼順序完成任務。
考慮以下程式碼片段:
func sum(a []int, c chan int) { fmt.Println("summing: ", a) total := 0 for _, v := range a { total += v } c <- total // send total to c } func main() { c := make(chan int) go sum([]int{1,2,3}, c) go sum([]int{4,5,6}, c) x := <-c fmt.Println(x) x = <-c fmt.Println(x) }
在此範例中,有兩個 goroutine啟動來計算兩個整數切片的總和。但是,它們的執行順序和列印結果的順序並不確定。您可以將輸出觀察為:
summing: [4 5 6] 15 summing: [1 2 3] 6
或
summing: [1 2 3] 6 summing: [4 5 6] 15
要同步Goroutines 的執行順序,可以採用多種方法:
使用阻塞通道:
透過使用通道的阻塞性質,您可以強制main goroutine 等待每個goroutine 完成,然後再繼續下一個。例如:
func main() { c := make(chan int) go sum([]int{1, 2, 3}, c) // Blocks until a value is received x := <-c fmt.Println(x) // Execute the next goroutine go sum([]int{4, 5, 6}, c) x = <-c fmt.Println(x) }
使用等待群組:
另一種常見的同步技術涉及使用等待群組。等待群組追蹤仍在運行的 goroutine 數量,並等待它們全部完成,然後再繼續下一步。以下是在上面的範例中使用等待群組的方法:
func sum(a []int, c chan int, wg *sync.WaitGroup) { defer wg.Done() fmt.Println("summing: ", a) total := 0 for _, v := range a { total += v } c <- total // send total to c } func main() { c := make(chan int) wg := new(sync.WaitGroup) // Increment the wait group wg.Add(1) // Launch the first goroutine go sum([]int{1, 2, 3}, c, wg) // Wait for the first goroutine to complete wg.Wait() // Increment the wait group again wg.Add(1) // Launch the second goroutine go sum([]int{4, 5, 6}, c, wg) // Wait for the second goroutine to complete wg.Wait() // Close the channel to indicate that no more values will be sent close(c) // Range over the channel to receive the results for theSum := range c { x := theSum fmt.Println(x) } }
透過將同步技術合併到程式碼中,您可以更好地控制 goroutine 的執行順序,確保它們在所需的順序。
以上是Go中如何控制Goroutines的執行順序?的詳細內容。更多資訊請關注PHP中文網其他相關文章!