2013-07-28 27 views
2

如果我錯了,請糾正我。只要我知道,goroutine的作品大致類似於線程。所以,如果我用不同的參數產生相同的功能前綴與去。它應該工作得很好嗎?奇怪的Goroutines行爲

package main 

import "fmt" 


func f(from string) { 
    for i := 0; i < 3; i++ { 
     fmt.Println(from, ":", i) 
    } 
} 

func main() { 
    go f("direct") 
    go f("redirect") 
    //var input string 
    //fmt.Scanln(&input) 

} 

實際輸出:

[email protected]:~/programs/go$ go run goroutine.go 
[email protected]:~/programs/go$ 

我剛剛回來的提示。

預期輸出:

direct : 0 
direct : 1 
direct : 2 
redirect : 0 
redirect : 1 
redirect : 2 

以相同的順序不一定。
無法理解這種奇怪的行爲。我錯過了什麼嗎?

編輯:添加掃描語句解決它。但是有沒有更好的方法來做到這一點?

回答

6

當主退出時,無論其他goroutine的狀態如何,程序都會終止。您可以在主要功能結束時添加select{}來測試此功能。這將導致main永遠不會退出,您將看到其他的goroutine運行。

如果您希望您的程序在兩個goroutine完成時都乾淨地退出(沒有死鎖),那麼您需要使用類似通道或sync.Waitgroup的內容來協調主結束。

示例使用sync.Waitgroup:

package main 

import (
    "fmt" 
    "sync" 
) 

func f(from string, wg *sync.WaitGroup) { 
    for i := 0; i < 3; i++ { 
     fmt.Println(from, ":", i) 
    } 

    wg.Done() 
} 

func main() { 
    wg := new(sync.WaitGroup) 
    wg.Add(2) 

    go f("direct", wg) 
    go f("redirect", wg) 

    wg.Wait() 
} 

示例使用渠道:

package main 

import (
    "fmt" 
) 

func f(from string, ch chan<- bool) { 
    for i := 0; i < 3; i++ { 
     fmt.Println(from, ":", i) 
    } 

    ch <- true 
} 

func main() { 
    ch := make(chan bool) 

    go f("direct", ch) 
    go f("redirect", ch) 

    <-ch 
    <-ch 
} 
+0

加入select {}看起來像一個黑客。我得到以下結果:所有goroutines都睡着了 - 僵局! 夠程1選擇(無例)]: main.main() \t /home/rahul/programs/go/goroutine.go:15 + 0x53 夠程2 [系統調用]: 由runtime.main 創建\t /build/buildd/golang-1/src/pkg/runtime/proc.c:221 退出狀態2 – Rahul

+1

是的,'select {}'是一個黑客。但是顯示問題。正如我在答覆中所述,使用併發類型(例如頻道或同步包中的某個內容)是處理此問題的正確方法。 –

+0

現在這一切都有道理。感謝斯蒂芬! – Rahul

0

如上到底選擇{}使得顯示確定輸出的說明,但你不能指望去例程以特殊順序運行。

如果你運行parallell go例程,那麼它們將以什麼樣的順序運行。你不能排除它們按順序運行,因爲它們並行運行!

您可能會在一臺機器上一次又一次地獲得預期的輸出時間,但不能保證打印輸出在任何給定機器上都是按順序排列的!