我是GO新手,我试图弄清楚goroutines如何工作以及如何使其同步。
这是我编写的一个简单程序,旨在了解有关它们的信息:

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

add函数将两个int求和,然后将结果传递给chan。
打印机功能从chan获取结果并进行打印。
这两个函数在main()中被称为goroutine,因此我还传递了一个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

问题在哪里和什么地方?

谢谢!

最佳答案

以下作品。我的意思是,它不会死锁。
由于您在通道的范围循环中具有打印机功能,因此在通道关闭后它将自动停止。我在末尾添加了3秒的延迟,以提供try循环时间进行打印。 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")
}

关于go - golang :学习goroutine让我陷入僵局,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/29479562/

10-14 13:37