簡體   English   中英

Golang頻道,執行順序

[英]Golang channels, order of execution

我正在學習Go,並且遇到了以下代碼片段:

package main

import "fmt"

func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int, 2)
    go sum(a[0:3], c)
    go sum(a[3:6], c)
    x := <-c
    y := <-c
    // x, y := <-c, <-c // receive from c

    fmt.Println(x, y)
}

Output:

-5 17

Program exited.

有人可以告訴我為什么“ sum”函數的第二個調用在第一個調用之前通過通道嗎? 在我看來,輸出應為:

17 -5

我還使用無緩沖通道對此進行了測試,它也給出了相同順序的輸出。 我想念什么?

您正在代碼中調用go例程,但無法確定該例程何時結束並將該值傳遞到緩沖的通道。

由於此代碼是異步的,因此只要例程完成,它將把數據寫入通道,並在另一側讀取。 在上面的示例中,您僅調用兩個go例程,因此行為是確定的,並且在大多數情況下都會以某種方式生成相同的輸出,但是當您增加go例程時,輸出將不會相同,並且順序會有所不同,除非您執行以下操作它同步。

例:

package main

import "fmt"

func sum(a []int, c chan int) {
    sum := 0
    for _, v := range a {
        sum += v
    }
    c <- sum // send sum to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 2, 4, 2, 8, 2, 7, 2, 99, -32, 2, 12, 32, 44, 11, 63}

    c := make(chan int)
    for i := 0; i < len(a); i = i + 5 {
        go sum(a[i:i+5], c)
    }
    output := make([]int, 5)
    for i := 0; i < 4; i++ {
        output[i] = <-c
    }
    close(c)

    fmt.Println(output)
}

此代碼在不同樣本運行中的輸出為

 [12 18 0 78 162] [162 78 12 0 18] [12 18 78 162 0] 

這是因為goroutines將輸出異步寫入緩沖的通道。

希望這可以幫助。

Goroutine是異步啟動的,它們可以按任何順序寫入通道。 比較容易看出您是否對示例進行了一點修改:

package main

import (
    "fmt"
    "time"
)

func sum(a []int, c chan int, name string, sleep int) {
    fmt.Printf("started goroutine: %s\n", name)
    time.Sleep(time.Second * time.Duration(sleep))

    sum := 0

    for _, v := range a { 
        sum += v
    }   
    fmt.Printf("about end goroutine: %s\n", name)
    c <- sum // send sum to c
}

func main() {
    a := []int{7, 2, 8, -9, 4, 0}

    c := make(chan int, 2)
    go sum(a[0:3], c, "A", 1)
    go sum(a[3:6], c, "B", 1)
    x := <-c 
    y := <-c 
    // x, y := <-c, <-c // receive from c

    fmt.Println(x, y)
}

https://play.golang.org/p/dK4DT0iUfzY

結果:

started goroutine: B
started goroutine: A
about end goroutine: A
about end goroutine: B
17 -5

運行golang.org沙箱時,每次都得到相同的結果。 如上所述。 但是,當我在自己的沙箱(在計算機上)上運行相同的代碼段時,有時會更改線程的順序。 這更加令人滿意。 它表明我不能指望任何特定的線程執行順序,這很直觀。 我只是不知道為什么我得到了相同的執行順序,這與線程啟動的順序相反。 我認為這只是golang.org沙盒上抽獎的好運。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM