2015-09-20 60 views
2
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) 
    go sum(a[len(a)/2:], c) 
    go sum(a[:len(a)/2], c) 

    x, y := <-c, <-c // receive from c 

    fmt.Println(x, y, x+y) 
} 

x, y := <-c, <-c // receive from cgoroutine輸出到頻道順序固定?

爲什麼這條線總是打印相同的結果呢?

我覺得應該是50/50機會打印 17 -5 12-5 17 12

我覺得兩個走程序應該是平行的

提前感謝!

package main 

import "fmt" 
import "time" 
import "math/rand" 

func sum(a []int, c chan int) { 
    sum := 0 
    for _, v := range a { 
     sum += v 
    } 
    time.Sleep(time.Millisecond * time.Duration(rand.Intn(1000))) 
    c <- sum // send sum to c 

} 

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

    c := make(chan int) 
    go sum(a[len(a)/2:], c) 
    go sum(a[:len(a)/2], c) 

    x, y := <-c, <-c // receive from c 

    fmt.Println(x, y, x+y) 
} 

我讓線程睡覺,但同樣的事情發生。我仍然感到困惑。

+0

您使用的是Go 1.5嗎?還有多少核心? – OneOfOne

+0

是go1.5一個核心 – Shawn

+0

@Shawn把睡眠放在這樣的功能的末尾不會有你正在尋找的效果。此外,主函數並不等待終止之前的睡眠完成執行,所以睡眠基本上什麼都不做。 –

回答

2

假設它應該是50/50的機率在這種情況下是不正確的。要清楚,我並不是說它應該總是一個或另一個,而是你不應該指望它每次程序運行時都會改變。行爲不一定是隨機的(甚至是僞隨機的)。

goroutine的保證不是將它安排在隨機的未來時間,而只是它將在未來的某個時間運行。如果調度程序的當前實現決定將goroutine放在一個簡單的隊列中,那麼它並不意味着它會被破壞。對於您的特定代碼的情況,如果您在不同的地方粘貼了幾個time.Sleepfmt.Printf,您可能會看到訂單有時會發生變化。

我在想,如果您將Go的調度程序選擇下一個goroutine與select與渠道一起使用時記錄的僞隨機行爲混爲一談。那裏的行爲被定義爲隨機的,並且說012行爲應該具有50/50的機會是正確的。

據我所知,運行時選擇哪個goroutine並不是隨機的。這不同於說它不能隨機,但更重要的是,它不是假設是隨機的。

重要的是你的代碼不應該關心goroutines的調度順序。無論它總是像排隊,還是倒退(堆棧),或隨機,或其他(可能是現實)。

+0

我讓線程睡覺,但同樣的事情發生。我仍然感到困惑。 – Shawn

+0

謝謝你的方式.. – Shawn

+0

@Shawn你把睡眠後的價值被放置在頻道,這不會有你要找的效果。 –