Go协程和通道不并行运行

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

Go-routines with channels not running parallely

问题

package main
import "time"

func main() {
    stringCh := make(chan func() string)
    go func() {
        stringCh <- func() string {
            return stringReturner()
        }
        close(stringCh)
    }()

    intCh := make(chan func() int)
    go func() {
        intCh <- func() int {
            return intReturner()
        }
        close(intCh)
    }()

    str := (<-stringCh)()
    print("Printing str: ", str,"\n\n")
    num := (<-intCh)()
    print("Printing int: ", num,"\n\n")        
}

func intReturner() int {
    time.Sleep(5 * time.Second)
    print("Inside int returner\n\n")
    return 1
}

func stringReturner() string {
    time.Sleep(5 * time.Second)
    print("Inside string returner\n\n")
    return "abcd"
}

输出:

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执行之后执行?

英文:
package main
import &quot;time&quot;
func main() {
	stringCh := make(chan func() (string))
	go func() {
		stringCh &lt;- func() (string) {
			return stringReturner()
		}
		close(stringCh)
	}()

	intCh := make(chan func() (int))
	go func() {
		intCh &lt;- func() (int) {
			return intReturner()
		}
		close(intCh)
	}()

	str := (&lt;-stringCh)()
	print(&quot;Printing str: &quot;, str,&quot;\n\n&quot;)
	num := (&lt;-intCh)()
	print(&quot;Printing int: &quot;, num,&quot;\n\n&quot;)		
}

func intReturner()int{
	time.Sleep(5 * time.Second)
	print(&quot;Inside int returner\n\n&quot;);
	return 1;
}

func stringReturner()string{
	time.Sleep(5 * time.Second)
	print(&quot;Inside string returner\n\n&quot;);
	return &quot;abcd&quot;;
}

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从两个通道读取数据。

var wg sync.WaitGroup
wg.Add(2)
go func() {
  defer wg.Done()
  str := (<-stringCh)()
  print("打印字符串: ", str, "\n\n")
}()
go func() {
  defer wg.Done()
  num := (<-intCh)()
  print("打印整数: ", num, "\n\n")
}()
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

var wg sync.WaitGroup
wg.Add(2)
go func() {
  defer wg.Done()
  str := (&lt;-stringCh)()
  print(&quot;Printing str: &quot;, str, &quot;\n\n&quot;)
}()
go func() {
  defer wg.Done()
  num := (&lt;-intCh)()
  print(&quot;Printing int: &quot;, num, &quot;\n\n&quot;)
}()
wg.Wait()

答案3

得分: 1

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

package main

import "time"

func main() {
    stringCh := make(chan func() string)
    go func() {
        time.Sleep(5 * time.Second)
        stringCh <- func() string {
            return stringReturner()
        }
        close(stringCh)
    }()

    intCh := make(chan func() int)
    go func() {
        time.Sleep(5 * time.Second)
        intCh <- func() int {
            return intReturner()
        }
        close(intCh)
    }()

    str := (<-stringCh)()
    print("Printing str: ", str, "\n\n")
    num := (<-intCh)()
    print("Printing int: ", num, "\n\n")
}

func intReturner() int {
    print("Inside int returner\n\n")
    return 1
}

func stringReturner() string {
    print("Inside string returner\n\n")
    return "abcd"
}

输出:

Inside string returner

Printing str: abcd

Inside int returner

Printing int: 1
英文:

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

package main

import &quot;time&quot;

func main() {
	stringCh := make(chan func() string)
	go func() {
		time.Sleep(5 * time.Second)
		stringCh &lt;- func() string {
			return stringReturner()
		}
		close(stringCh)
	}()

	intCh := make(chan func() int)
	go func() {
		time.Sleep(5 * time.Second)
		intCh &lt;- func() int {
			return intReturner()
		}
		close(intCh)
	}()

	str := (&lt;-stringCh)()
	print(&quot;Printing str: &quot;, str, &quot;\n\n&quot;)
	num := (&lt;-intCh)()
	print(&quot;Printing int: &quot;, num, &quot;\n\n&quot;)
}

func intReturner() int {
	print(&quot;Inside int returner\n\n&quot;)
	return 1
}

func stringReturner() string {
	print(&quot;Inside string returner\n\n&quot;)
	return &quot;abcd&quot;
}

Output:

Inside string returner

Printing str: abcd

Inside int returner

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:

确定