Go协程和通道不并行运行

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

Go-routines with channels not running parallely

问题

  1. package main
  2. import "time"
  3. func main() {
  4. stringCh := make(chan func() string)
  5. go func() {
  6. stringCh <- func() string {
  7. return stringReturner()
  8. }
  9. close(stringCh)
  10. }()
  11. intCh := make(chan func() int)
  12. go func() {
  13. intCh <- func() int {
  14. return intReturner()
  15. }
  16. close(intCh)
  17. }()
  18. str := (<-stringCh)()
  19. print("Printing str: ", str,"\n\n")
  20. num := (<-intCh)()
  21. print("Printing int: ", num,"\n\n")
  22. }
  23. func intReturner() int {
  24. time.Sleep(5 * time.Second)
  25. print("Inside int returner\n\n")
  26. return 1
  27. }
  28. func stringReturner() string {
  29. time.Sleep(5 * time.Second)
  30. print("Inside string returner\n\n")
  31. return "abcd"
  32. }

输出:

Inside string returner

Printing str: abcd

等待5秒

Inside int returner

Printing int: 1

https://play.golang.org/p/oE2ybs7Jo-W

为什么这段代码执行需要10秒而不是5秒?我们通过同时启动两个goroutine(一个用于stringReturner,一个用于intReturner)来并行调用,但为什么intReturner在stringReturner执行之后执行?

英文:
  1. package main
  2. import &quot;time&quot;
  3. func main() {
  4. stringCh := make(chan func() (string))
  5. go func() {
  6. stringCh &lt;- func() (string) {
  7. return stringReturner()
  8. }
  9. close(stringCh)
  10. }()
  11. intCh := make(chan func() (int))
  12. go func() {
  13. intCh &lt;- func() (int) {
  14. return intReturner()
  15. }
  16. close(intCh)
  17. }()
  18. str := (&lt;-stringCh)()
  19. print(&quot;Printing str: &quot;, str,&quot;\n\n&quot;)
  20. num := (&lt;-intCh)()
  21. print(&quot;Printing int: &quot;, num,&quot;\n\n&quot;)
  22. }
  23. func intReturner()int{
  24. time.Sleep(5 * time.Second)
  25. print(&quot;Inside int returner\n\n&quot;);
  26. return 1;
  27. }
  28. func stringReturner()string{
  29. time.Sleep(5 * time.Second)
  30. print(&quot;Inside string returner\n\n&quot;);
  31. return &quot;abcd&quot;;
  32. }

Output:

Inside string returner

Printing str: abcd

WAIT OF 5 SECONDS

Inside int returner

Printing int: 1

https://play.golang.org/p/oE2ybs7Jo-W

Why is this coding taking 10 seconds to execute instead of 5? We are parallelizing the calls by spawning two go-routines right (1 for string returner and 1 for int returner), but why is the int returner executing after the string returner executes?

答案1

得分: 3

该通道返回一个带有延时的函数,并且这个函数按顺序调用。这就是为什么通常需要10秒的原因。

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

英文:

The channel is returning function with sleep, and such function got called in sequential manner. That is why it will take 10s in general.

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

答案2

得分: 1

这是因为你只是并行地向通道写入数据,但是从通道读取数据是按顺序进行的。要解决这个问题,你可以使用单独的goroutine从两个通道读取数据。

  1. var wg sync.WaitGroup
  2. wg.Add(2)
  3. go func() {
  4. defer wg.Done()
  5. str := (<-stringCh)()
  6. print("打印字符串: ", str, "\n\n")
  7. }()
  8. go func() {
  9. defer wg.Done()
  10. num := (<-intCh)()
  11. print("打印整数: ", num, "\n\n")
  12. }()
  13. wg.Wait()
英文:

Thats because you are only writing to the channels parallelly. But the read from the channels are happening one-after-the-other. To fix this, you can read from both channels from separate go routines

  1. var wg sync.WaitGroup
  2. wg.Add(2)
  3. go func() {
  4. defer wg.Done()
  5. str := (&lt;-stringCh)()
  6. print(&quot;Printing str: &quot;, str, &quot;\n\n&quot;)
  7. }()
  8. go func() {
  9. defer wg.Done()
  10. num := (&lt;-intCh)()
  11. print(&quot;Printing int: &quot;, num, &quot;\n\n&quot;)
  12. }()
  13. wg.Wait()

答案3

得分: 1

根据建议,将sleep方法移入go routine以在5秒内同时运行两个函数:

  1. package main
  2. import "time"
  3. func main() {
  4. stringCh := make(chan func() string)
  5. go func() {
  6. time.Sleep(5 * time.Second)
  7. stringCh <- func() string {
  8. return stringReturner()
  9. }
  10. close(stringCh)
  11. }()
  12. intCh := make(chan func() int)
  13. go func() {
  14. time.Sleep(5 * time.Second)
  15. intCh <- func() int {
  16. return intReturner()
  17. }
  18. close(intCh)
  19. }()
  20. str := (<-stringCh)()
  21. print("Printing str: ", str, "\n\n")
  22. num := (<-intCh)()
  23. print("Printing int: ", num, "\n\n")
  24. }
  25. func intReturner() int {
  26. print("Inside int returner\n\n")
  27. return 1
  28. }
  29. func stringReturner() string {
  30. print("Inside string returner\n\n")
  31. return "abcd"
  32. }

输出:

  1. Inside string returner
  2. Printing str: abcd
  3. Inside int returner
  4. Printing int: 1
英文:

Based on the suggestions moving the sleep method into go routine to run both functions concurrently in 5s:

  1. package main
  2. import &quot;time&quot;
  3. func main() {
  4. stringCh := make(chan func() string)
  5. go func() {
  6. time.Sleep(5 * time.Second)
  7. stringCh &lt;- func() string {
  8. return stringReturner()
  9. }
  10. close(stringCh)
  11. }()
  12. intCh := make(chan func() int)
  13. go func() {
  14. time.Sleep(5 * time.Second)
  15. intCh &lt;- func() int {
  16. return intReturner()
  17. }
  18. close(intCh)
  19. }()
  20. str := (&lt;-stringCh)()
  21. print(&quot;Printing str: &quot;, str, &quot;\n\n&quot;)
  22. num := (&lt;-intCh)()
  23. print(&quot;Printing int: &quot;, num, &quot;\n\n&quot;)
  24. }
  25. func intReturner() int {
  26. print(&quot;Inside int returner\n\n&quot;)
  27. return 1
  28. }
  29. func stringReturner() string {
  30. print(&quot;Inside string returner\n\n&quot;)
  31. return &quot;abcd&quot;
  32. }

Output:

  1. Inside string returner
  2. Printing str: abcd
  3. Inside int returner
  4. Printing int: 1

huangapple
  • 本文由 发表于 2021年6月27日 12:55:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/68148113.html
匿名

发表评论

匿名网友

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

确定