2016-05-12 11 views
1

私の考えを正しいものにするために私がプレイしている私のゴランプログラムです。 私はプログラムを実行するとデッドロックしているのですが、私はその理由を理解していませんか? 何が悪いと指摘してください。プログラムのデッドロックが発生する

package main 

import (
    "fmt" 
    "sync" 
) 

var wg sync.WaitGroup 

func main() { 

    numOfGoRoutines := 10 
    wg.Add(numOfGoRoutines) 
    ch := make(chan int, numOfGoRoutines) 

    for i := 0; i < numOfGoRoutines; i++ { 
     a := i 
     go sqr(ch, a, wg) 
    } 
    wg.Wait() 
    fmt.Println("After WAIT") 
    close(ch) 
    var res int 
    for i := range ch { 
     res += i 
    } 
    ch = nil 
    fmt.Println("result = ", res) 

} 

func sqr(ch chan int, val int, wg sync.WaitGroup) { 
    fmt.Println("go - ", val) 
    s := val * val 
    ch <- s 
    wg.Done() 
} 

、出力は次のとおりです。

warning: GOPATH set to GOROOT (C:\\Go) has no effect 
go - 9 
go - 0 
go - 1 
go - 2 
go - 3 
go - 4 
go - 5 
go - 6 
go - 7 
go - 8 
fatal error: all goroutines are asleep - deadlock! 

goroutine 1 [semacquire]: 
sync.runtime_Semacquire(0x5bcabc) 
     C:/Go/src/runtime/sema.go:47 +0x2d 
sync.(*WaitGroup).Wait(0x5bcab0) 
     C:/Go/src/sync/waitgroup.go:127 +0xbb 
main.main() 
     C:/demo/go-work/main.go:20 +0xdf 
exit status 2 

答えて

3

問題はあなたではなく、参照よりも、ゴルーチンにsync.WaitGroupのコピーを渡しているということである(つまり、ポインタ):

package main 

import (
    "fmt" 
    "sync" 
) 

var wg sync.WaitGroup 

func main() { 

    numOfGoRoutines := 10 
    wg.Add(numOfGoRoutines) 
    ch := make(chan int, numOfGoRoutines) 

    for i := 0; i < numOfGoRoutines; i++ { 
     a := i 
     go sqr(ch, a, &wg) 
    } 
    wg.Wait() 
    fmt.Println("After WAIT") 
    close(ch) 
    var res int 
    for i := range ch { 
     res += i 
    } 
    ch = nil 
    fmt.Println("result = ", res) 

} 

func sqr(ch chan int, val int, wg *sync.WaitGroup) { 
    fmt.Println("go - ", val) 
    s := val * val 
    ch <- s 
    wg.Done() 
} 

さらに、wgはグローバル変数であるため、パラメータを完全に削除することもできます。

package main 

import (
    "fmt" 
    "sync" 
) 

var wg sync.WaitGroup 

func main() { 

    numOfGoRoutines := 10 
    wg.Add(numOfGoRoutines) 
    ch := make(chan int, numOfGoRoutines) 

    for i := 0; i < numOfGoRoutines; i++ { 
     a := i 
     go sqr(ch, a) 
    } 
    wg.Wait() 
    fmt.Println("After WAIT") 
    close(ch) 
    var res int 
    for i := range ch { 
     res += i 
    } 
    ch = nil 
    fmt.Println("result = ", res) 

} 

func sqr(ch chan int, val int) { 
    fmt.Println("go - ", val) 
    s := val * val 
    ch <- s 
    wg.Done() 
} 
+0

ああ、ref型と値型の違いはわかりませんが、とにかく感謝します。 –

+0

@Bovi_Khurjaすべては、マップ、スライス、チャンネルを除く値のタイプです。 – OneOfOne

関連する問題