2

間違っている場合は修正してください。私の知る限り、ゴルーチンはスレッドとほぼ同じように機能します。したがって、go の前に異なるパラメーターを付けて同じ関数を生成するとします。それは完全にうまくいくはずですか?

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)

}

実際の出力:

rahul@g3ck0:~/programs/go$ go run goroutine.go 
rahul@g3ck0:~/programs/go$ 

私はただプロンプトを返します。

期待される出力:

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

必ずしも同じ順序ではありません。
この奇妙な行動を理解することができません。何か不足していますか?

編集: Scan ステートメントを追加すると解決します。しかし、それを行うより良い方法はありますか?

4

2 に答える 2

6

main が終了すると、プログラムは他のゴルーチンの状態に関係なく終了します。select{}メイン関数の最後に追加することで、これをテストできます。これにより、メインが終了せず、他のゴルーチンが実行されます。

両方のゴルーチンが完了したときにプログラムを (デッドロックなしで) 正常に終了させたい場合は、channel や 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
}
于 2013-07-28T04:13:43.583 に答える
0

上で述べたように、最後の select{} は出力が確実に表示されるようにしますが、go ルーチンが特別な順序で実行されることは期待できません。

並行して go ルーチンを実行する場合、それらがどの順序で実行されるかは保証されません。それらは並行して実行されるため、それらを順次実行することを除外することはできません!

1 台のマシンで何度も期待どおりの出力が得られるかもしれませんが、特定のマシンで毎回正しい印刷結果が得られるという保証はありません!!

于 2013-07-29T08:30:11.087 に答える