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

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

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

问题

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

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

非常感谢任何帮助!

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. const (
  8. numPollers = 2 // 要启动的Poller goroutine数量
  9. )
  10. var urls = []string{
  11. "http://www.google.com/",
  12. "http://golang.org/",
  13. "http://blog.golang.org/",
  14. "http://golangtutorials.blogspot.fr",
  15. "https://gobyexample.com/",
  16. }
  17. // Resource 表示此程序要轮询的HTTP URL。
  18. type Resource struct {
  19. url string
  20. }
  21. func Poller(in <-chan *Resource, wg *sync.WaitGroup) {
  22. //defer wg.Done()
  23. for r := range in {
  24. fmt.Printf("Finished: %v - %v\n", r.url, time.Now())
  25. }
  26. wg.Done()
  27. }
  28. func main() {
  29. var wg sync.WaitGroup
  30. pending := make(chan *Resource)
  31. wg.Add(len(urls))
  32. go Poller(pending, &wg)
  33. go func() {
  34. for _, url := range urls {
  35. wg.Add(1)
  36. fmt.Println("SENT > Pending url " + url)
  37. pending <- &Resource{url: url}
  38. }
  39. }()
  40. wg.Wait()
  41. fmt.Printf("Finished all goroutines: %v\n", time.Now())
  42. }

链接: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都处于休眠状态-死锁。

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. &quot;time&quot;
  6. )
  7. const (
  8. numPollers = 2 // number of Poller goroutines to launch
  9. )
  10. var urls = []string{
  11. &quot;http://www.google.com/&quot;,
  12. &quot;http://golang.org/&quot;,
  13. &quot;http://blog.golang.org/&quot;,
  14. &quot;http://golangtutorials.blogspot.fr&quot;,
  15. &quot;https://gobyexample.com/&quot;,
  16. }
  17. // Resource represents an HTTP URL to be polled by this program.
  18. type Resource struct {
  19. url string
  20. }
  21. func Poller(in &lt;-chan *Resource, wg *sync.WaitGroup) {
  22. //defer wg.Done()
  23. for r := range in {
  24. fmt.Printf(&quot;Finished: %v - %v\n&quot;, r.url, time.Now())
  25. }
  26. wg.Done()
  27. }
  28. func main() {
  29. var wg sync.WaitGroup
  30. pending := make(chan *Resource)
  31. wg.Add(len(urls))
  32. go Poller(pending, &amp;wg)
  33. go func() {
  34. for _, url := range urls {
  35. wg.Add(1)
  36. fmt.Println(&quot;SENT &gt; Pending url &quot; + url)
  37. pending &lt;- &amp;Resource{url: url}
  38. }
  39. }()
  40. wg.Wait()
  41. fmt.Printf(&quot;Finished all goroutines: %v\n&quot;, time.Now())
  42. }

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

答案1

得分: 3

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

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. "time"
  6. )
  7. const (
  8. numPollers = 2 // 要启动的Poller goroutine的数量
  9. )
  10. var urls = []string{
  11. "http://www.google.com/",
  12. "http://golang.org/",
  13. "http://blog.golang.org/",
  14. "http://golangtutorials.blogspot.fr",
  15. "https://gobyexample.com/",
  16. }
  17. // Resource 表示此程序要轮询的HTTP URL。
  18. type Resource struct {
  19. url string
  20. }
  21. func Poller(in <-chan *Resource, wg *sync.WaitGroup) {
  22. defer wg.Done()
  23. for r := range in {
  24. fmt.Printf("Finished: %v - %v\n", r.url, time.Now())
  25. }
  26. }
  27. func main() {
  28. var wg sync.WaitGroup
  29. pending := make(chan *Resource)
  30. wg.Add(numPollers)
  31. go Poller(pending, &wg)
  32. go func() {
  33. defer close(pending)
  34. defer wg.Done()
  35. for _, url := range urls {
  36. fmt.Println("SENT > Pending url " + url)
  37. pending <- &Resource{url: url}
  38. }
  39. }()
  40. wg.Wait()
  41. fmt.Printf("Finished all goroutines: %v\n", time.Now())
  42. }

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:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. &quot;time&quot;
  6. )
  7. const (
  8. numPollers = 2 // number of Poller goroutines to launch
  9. )
  10. var urls = []string{
  11. &quot;http://www.google.com/&quot;,
  12. &quot;http://golang.org/&quot;,
  13. &quot;http://blog.golang.org/&quot;,
  14. &quot;http://golangtutorials.blogspot.fr&quot;,
  15. &quot;https://gobyexample.com/&quot;,
  16. }
  17. // Resource represents an HTTP URL to be polled by this program.
  18. type Resource struct {
  19. url string
  20. }
  21. func Poller(in &lt;-chan *Resource, wg *sync.WaitGroup) {
  22. defer wg.Done()
  23. for r := range in {
  24. fmt.Printf(&quot;Finished: %v - %v\n&quot;, r.url, time.Now())
  25. }
  26. }
  27. func main() {
  28. var wg sync.WaitGroup
  29. pending := make(chan *Resource)
  30. wg.Add(2)
  31. go Poller(pending, &amp;wg)
  32. go func() {
  33. defer close(pending)
  34. defer wg.Done()
  35. for _, url := range urls {
  36. fmt.Println(&quot;SENT &gt; Pending url &quot; + url)
  37. pending &lt;- &amp;Resource{url: url}
  38. }
  39. }()
  40. wg.Wait()
  41. fmt.Printf(&quot;Finished all goroutines: %v\n&quot;, time.Now())
  42. }

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:

确定