2012-06-26 80 views
0

我剛剛嘗試了下面的代碼,但結果似乎有點奇怪。它首先打印奇數,然後打印偶數。我真的很困惑。我曾希望它能一個接一個地輸出奇數和偶數,就像1,2,3,4 ...一樣。誰能幫我?去例行程序的奇怪行爲

package main 

import (
    "fmt" 
    "time" 
) 

func main() { 
    go sheep(1) 
    go sheep(2) 
    time.Sleep(100000) 
} 

func sheep(i int) { 
    for ; ; i += 2 { 
     fmt.Println(i,"sheeps") 
    } 
} 
+1

如果您至少在尋找幫助,那麼您可以用標題和標題來描述您的問題。 – Nit

回答

6

很可能你只用一個cpu線程運行。所以它運行第一個goroutine,然後運行第二個goroutine。如果你告訴它它可以在多個線程上運行,那麼只要os在CPU上有空閒時間就可以同時運行。在運行二進制文件之前,可以通過設置GOMAXPROCS = 2來演示這一點。或者你可以嘗試在你的綿羊函數中添加一個runtime.Gosched()調用,看看是否會觸發運行時允許另一個goroutine運行。

通常,儘管最好不要假定兩個goroutine中的操作之間的排序語義,除非您使用sync.Mutex指定特定同步點或在通道之間進行通信。

+0

我不認爲他是這麼認爲排序,因爲希望看到兩個進程同時運行,而不是顯然一個接一個地運行。我的猜測是,它應該是一個簡單的測試,看看例行公事的冷靜。既然如此,每次印刷之後的一小段睡眠也可能會訣竅,儘管它會明顯減慢速度。 – Derek

+0

當然,但對於任何在嘗試調試時發現此問題的人來說,這是非常有用的建議,所以我把它扔了進去。 –

3

未同步的goroutines以完全未定義的順序執行。如果你想打印出像

1 sheeps 
2 sheeps 
3 sheeps 
.... 

這個確切的順序,然後goroutines是做錯的方法。如果您不太關心事情發生的順序,那麼併發效果很好。

您可以通過同步(在fmt.Println調用或使用頻道周圍鎖定互斥鎖)來在您的程序中強制執行命令,但這沒有意義,因爲您可以更輕鬆地編寫使用單個goroutine的代碼。