Go Channel并使用指针变量执行例程,所有goroutine都处于睡眠状态 - 死锁

时间:2014-12-15 23:12:15

标签: go

我花了一个晚上看看如何解决这个错误,但我还没有成功。当我运行程序时,我有以下错误:“所有goroutines都睡着了 - 死锁!”。我理解这是因为主程序在例程可以执行其任务之前退出,我认为使用sync.WaitGroup会有所帮助但不是真的:/

我想设置一些例程和使用频道来发送网址以检查http状态代码。我想限制对网站的并发调用次数。我跟着例子用字符串而不是结构做同样的事情,它起作用了。

任何帮助都将受到赞赏:)

package main

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

const (
    numPollers = 2                // number of Poller goroutines to launch
)

var urls = []string{
    "http://www.google.com/",
    "http://golang.org/",
    "http://blog.golang.org/",
    "http://golangtutorials.blogspot.fr",
    "https://gobyexample.com/",
}

// Resource represents an HTTP URL to be polled by this program.
type Resource struct {
    url      string
}

func Poller(in <-chan *Resource, wg *sync.WaitGroup) {
    //defer wg.Done()
    for r := range in {
        fmt.Printf("Finished: %v - %v\n", r.url, time.Now())
    }
    wg.Done()
}

func main() {
    var wg sync.WaitGroup
    pending := make(chan *Resource)

    wg.Add(len(urls))

    go Poller(pending, &wg)

    go func() {
        for _, url := range urls {
            wg.Add(1)
            fmt.Println("SENT > Pending url " + url)
            pending <- &Resource{url: url}
        }
    }()

    wg.Wait()

    fmt.Printf("Finished all goroutines: %v\n", time.Now())
}

https://play.golang.org/p/B-HSiDo2Qg

2 个答案:

答案 0 :(得分:3)

首先,您对wg.Add()的呼叫过多。你为每个正在运行的goroutine召唤一次。见http://golang.org/pkg/sync/#WaitGroup。其次,在完成写入之后,您没有关闭频道。这是您的代码的修改版本:

package main

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

const (
    numPollers = 2                // number of Poller goroutines to launch
)

var urls = []string{
    "http://www.google.com/",
    "http://golang.org/",
    "http://blog.golang.org/",
    "http://golangtutorials.blogspot.fr",
    "https://gobyexample.com/",
}

// Resource represents an HTTP URL to be polled by this program.
type Resource struct {
    url      string
}

func Poller(in <-chan *Resource, wg *sync.WaitGroup) {
    defer wg.Done()
    for r := range in {
        fmt.Printf("Finished: %v - %v\n", r.url, time.Now())
    }
}

func main() {
    var wg sync.WaitGroup
    pending := make(chan *Resource)

    wg.Add(2)

    go Poller(pending, &wg)

    go func() {
        defer close(pending)
        defer wg.Done()
        for _, url := range urls {
            fmt.Println("SENT > Pending url " + url)
            pending <- &Resource{url: url}
        }
    }()

    wg.Wait()

    fmt.Printf("Finished all goroutines: %v\n", time.Now())
}

https://play.golang.org/p/ucUlZEZMZM

答案 1 :(得分:1)

你忘了关闭频道,你的等待组太长了。这对我有用:https://play.golang.org/p/yasIzaCbmQ