2015-04-06 45 views
-1

我是GO新手,我想弄清楚goroutines是如何工作的以及如何同步它們。 這是一個簡單的程序,我寫來了解他們的東西:GOLANG:學習goroutine使我陷入僵局

package main 

import (
     "fmt" 
     "sync" 
     "time" 
) 

func printAfterDelay(delay time.Duration, message string, wg *sync.WaitGroup) { 
     time.Sleep(delay) 
     fmt.Println(message) 
     wg.Done() 
} 

func add(a int, b int, chan1 chan int, wg *sync.WaitGroup) { 
     c := a + b 
     chan1 <- c 
     //close(chan1) 
     wg.Done() 
} 

func printer(chan1 chan int, wg *sync.WaitGroup) { 
     for result := range chan1 { 
       //result := <-chan1 
       //time.Sleep(2000 * time.Millisecond) 
       fmt.Println(result) 
     } 
     close(chan1) 
     wg.Done() 
} 

func main() { 
     //var wg sync.WaitGroup 
     wg := &sync.WaitGroup{} 

     fmt.Println("Start...") 

     wg.Add(1) 
     go printAfterDelay(2000*time.Millisecond, "Try", wg) 

     chan1 := make(chan int) 
     wg.Add(1) 
     go add(5, 4, chan1, wg) 

     wg.Add(1) 
     go add(3, 1, chan1, wg) 

     wg.Add(1) 
     go printer(chan1, wg) 

     //time.Sleep(3000 * time.Millisecond) 
     wg.Wait() 

     fmt.Println("End") 
} 

的附加功能需要兩個int,對其求和,並將結果傳遞給議員。 打印機功能從chan中取得結果並打印出來。 這兩個函數在main()中作爲goroutines被調用,所以我還傳遞了一個WaitGroup作爲指針,在調用goroutine之前遞增並在函數結束時遞減。

反正當我執行編譯後的程序將打印:

Start... 
9 
4 
Try 
fatal error: all goroutines are asleep - deadlock! 
goroutine 16 [semacquire]: 
sync.runtime_Semacquire(0x18334008) 
    /usr/lib/go/src/pkg/runtime/sema.goc:199 +0x37 
sync.(*WaitGroup).Wait(0x183240e0) 
    /usr/lib/go/src/pkg/sync/waitgroup.go:129 +0x12d 
main.main()   
    /home/ettore/go/src/example/goroutine/main.go:52 +0x1e5 

goroutine 19 [finalizer wait]: 
runtime.park(0x80599e0, 0x814f000, 0x814e3e9) 
    /usr/lib/go/src/pkg/runtime/proc.c:1369 +0x94 
runtime.parkunlock(0x814f000, 0x814e3e9)  
    /usr/lib/go/src/pkg/runtime/proc.c:1385 +0x3 
frunfinq()   
    /usr/lib/go/src/pkg/runtime/mgc0.c:2644 +0xc5 
runtime.goexit()   
    /usr/lib/go/src/pkg/runtime/proc.c:1445 

goroutine 23 [chan receive]: 
main.printer(0x1831a090, 0x183240e0)   
    /home/ettore/go/src/example/goroutine/main.go:23 +0x46 
created by main.main   
    /home/ettore/go/src/example/goroutine/main.go:49 +0x1d7 

在哪裏,是什麼問題(S)?

謝謝!

+1

您是否試過閱讀文檔? – Azat

回答

1

以下工作。我的意思是說它沒有死鎖。 由於您在通道範圍循環中具有打印機功能,因此通道關閉後它會自動停止。我在接近結束處添加了3秒的延遲時間來給出打印循環時間。 Read the documentation though. It'll explain 100% of these details.

package main 

import (
     "fmt" 
     "sync" 
     "time" 
) 

func printAfterDelay(delay time.Duration, message string, wg *sync.WaitGroup) { 
     time.Sleep(delay) 
     fmt.Println(message) 

} 

func add(a int, b int, chan1 chan int, wg *sync.WaitGroup) { 
     c := a + b 
     chan1 <- c 
     wg.Done() 
} 

func printer(chan1 chan int, wg *sync.WaitGroup) { 
     for result := range chan1 { 
       fmt.Println(result) 
     } 
} 

func main() { 
     //var wg sync.WaitGroup 
     wg := &sync.WaitGroup{} 

     fmt.Println("Start...") 

     go printAfterDelay(2000*time.Millisecond, "Try", wg) 

     chan1 := make(chan int) 
     wg.Add(1) 
     go add(5, 4, chan1, wg) 

     wg.Add(1) 
     go add(3, 1, chan1, wg) 

     go printer(chan1, wg) 

     time.Sleep(3000 * time.Millisecond) 
     wg.Wait() 
    close(chan1) 

     fmt.Println("End") 
} 
+0

順便說一下,您可以完全刪除waitgroup,因爲打印機功能將「凍結」,並等待通道中有值讀取或關閉。 –

+0

謝謝!我保證我會閱讀整個文檔... – Noettore

+0

不,您確實需要waitgroup(或等價物)。否則,不能保證發送功能將在您關閉頻道之前進行競爭,您將會感到恐慌。切勿使用睡眠進行同步。 – JimB