2016-05-12 95 views
1

這是我玩的Golang程序,爲了讓我的概念正確。 當我運行該程序時,它陷入了僵局,我不明白爲什麼? 請有人指出哪裏出了問題?Go程序陷入僵局

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