Go Channel和Go协程与指针变量,所有的goroutine都处于休眠状态-死锁。

huangapple go评论76阅读模式
英文:

Go Channel and go routine with pointer variables all goroutines are asleep - deadlock

问题

我花了整个晚上来解决这个错误,但是没有成功。当我运行程序时,出现了以下错误:"所有的goroutine都处于休眠状态 - 死锁!"。我理解这是因为主程序在例程有机会执行任务之前就退出了,我原以为使用sync.WaitGroup会有所帮助,但实际上并没有解决问题。

我想设置一定数量的例程,并使用通道发送URL以检查HTTP状态码。我想限制对网站的并发调用数量。我已经按照使用字符串而不是结构体的示例进行了操作,它是有效的。

非常感谢任何帮助!

package main

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

const (
	numPollers = 2 // 要启动的Poller goroutine数量
)

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

// Resource 表示此程序要轮询的HTTP URL。
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

英文:

I spend my evening looking at how to fix this error but I haven't succeeded. When I run the program I have the following error : "all goroutines are asleep - deadlock!". I understand this is because the main program is exited before the routine has the possibility to do its tasks and I thought using sync.WaitGroup would help but not really :/

I want to set a number of routine and use channels to send urls in order to check http status code. I want to limit the number of concurrency call to a website. I've followed examples doing the same thing with string instead of struct and it worked.

Any help would be well appreciated Go Channel和Go协程与指针变量,所有的goroutine都处于休眠状态-死锁。

package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
	&quot;time&quot;
)

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

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

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

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

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

	wg.Add(len(urls))

	go Poller(pending, &amp;wg)

	go func() {
		for _, url := range urls {
			wg.Add(1)
			fmt.Println(&quot;SENT &gt; Pending url &quot; + url)
			pending &lt;- &amp;Resource{url: url}
		}
	}()

	wg.Wait()

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

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

答案1

得分: 3

首先,你对wg.Add()的调用次数太多了。你为每个运行的goroutine调用了一次。请参考http://golang.org/pkg/sync/#WaitGroup。其次,在写入完成后,你没有关闭通道。这是你代码的修改版本:

package main

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

const (
    numPollers = 2 // 要启动的Poller goroutine的数量
)

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

// Resource 表示此程序要轮询的HTTP URL。
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(numPollers)

    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

英文:

First, you have too many calls to wg.Add(). You call that once for each goroutine you're running. See http://golang.org/pkg/sync/#WaitGroup. Second, you didn't close the channel after you were done writing to it. Here's a modified version of your code:

package main

import (
    &quot;fmt&quot;
    &quot;sync&quot;
    &quot;time&quot;
)

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

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

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

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

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

    wg.Add(2)

    go Poller(pending, &amp;wg)

    go func() {
        defer close(pending)
        defer wg.Done()
        for _, url := range urls {
            fmt.Println(&quot;SENT &gt; Pending url &quot; + url)
            pending &lt;- &amp;Resource{url: url}
        }
    }()

    wg.Wait()

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

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

答案2

得分: 1

你忘记关闭通道,并且你的等待组时间太长。这个链接对我有用:https://play.golang.org/p/yasIzaCbmQ

英文:

You forget to close channel, and your wait group is too long. This works for me: https://play.golang.org/p/yasIzaCbmQ

huangapple
  • 本文由 发表于 2014年12月16日 07:12:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/27494857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定