2016-05-12 5 views
1

Hier ist mein Golang-Programm, mit dem ich gerade spiele, um meine Konzepte richtig zu machen. Wenn ich das Programm ausführen, ist es festgefahren, ich verstehe nicht warum? Bitte jemand darauf hinweisen, was schief läuft?Go-Programm wird Deadlock

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() 
} 

und der Ausgang ist:

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 

Antwort

3

Das Problem ist, dass Sie eine Kopie von sync.WaitGroup den goroutines vorbei sind, eher als eine Referenz (dh ein Zeiger):

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() 
} 

Zusätzlich, da wg eine globale Variable ist, können Sie den Parameter einfach ganz entfernen:

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

Ah, es ist schwer zu wissen, was ist ein Ref-Typ und was ist Werttyp, aber trotzdem danke. –

+0

@Bovi_Khurja alles ist ein Werttyp außer Karten, Scheiben, Kanäle. – OneOfOne