2015-04-06 1 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, суммирует их и передать результат в чан. Функция принтера извлекает результаты из Чан и печатает их. Две функции вызываются в main() как goroutines, поэтому я также передал WaitGroup как указатель, который увеличивается до вызова goroutines и уменьшается при завершении функций.

Во всяком случае, когда я исполняю скомпилированную программу печатает:

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 

Где и в чем проблема (ы)?

Спасибо!

+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