并发执行但序列化输出

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

Concurrent execution but serialized output

问题

我需要使用名为g1g2g3的3个goroutine,并以轮询的方式在这3个goroutine之间分配1-10的数字。它们将根据提供的数字执行一些假设的工作。程序应以以下方式打印输出。

g1-1<br/>
g2-2<br/>
g3-3<br/>
g1-4<br/>
g2-5<br/>
g3-6<br/>
...

任务必须并发执行,但输出必须按顺序进行。

我已经实现了下面的代码来分配数字并打印输出,但输出的打印顺序不如上述所述。

我需要一些帮助来修复下面的代码,或者对实现上述所需输出的其他方法提出建议。

方法1:

  1. package main
  2. import (
  3. "fmt"
  4. "sync"
  5. )
  6. func main() {
  7. chang1 := make(chan int)
  8. chang2 := make(chan int)
  9. chang3 := make(chan int)
  10. var wg sync.WaitGroup
  11. wg.Add(3)
  12. go func() {
  13. for num := range chang1 {
  14. fmt.Println("g1", num)
  15. }
  16. wg.Done()
  17. }()
  18. go func() {
  19. for num := range chang2 {
  20. fmt.Println("g2", num)
  21. }
  22. wg.Done()
  23. }()
  24. go func() {
  25. for num := range chang3 {
  26. fmt.Println("g3", num)
  27. }
  28. wg.Done()
  29. }()
  30. channels := []chan int{chang1, chang2, chang3}
  31. for i := 1; i <= 10; i++ {
  32. currentCh := (i - 1) % 3
  33. channels[currentCh] <- i
  34. }
  35. close(chang1)
  36. close(chang2)
  37. close(chang3)
  38. wg.Wait()
  39. }

输出(顺序不正确)

g1- 1<br>
g1- 4<br>
g2- 2<br>
g3- 3<br>
g1- 7<br>
g2- 5<br>
g2- 8<br>
g3- 6<br>
g3- 9<br>
g1- 10<br>
...

英文:

I need to use 3 goroutines named g1, g2, g3. and distribute numbers from 1-10 among the above 3 goroutines in a round-robin fashion. They will do some hypothetical work based on the provided number. And program should print output in the following manner.

g1-1<br/>
g2-2<br/>
g3-3<br/>
g1-4<br/>
g2-5<br/>
g3-6<br/>
...

Tasks must be performed concurrently but the output must be in sequential order.

I have implemented the below code which distributes numbers and prints but output print order is not guaranteed as mentioned above.

I need some help to fix the below code or suggestions on another approach to get the above-desired output.

Approach 1:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;sync&quot;
  5. )
  6. func main() {
  7. chang1 := make(chan int)
  8. chang2 := make(chan int)
  9. chang3 := make(chan int)
  10. var wg sync.WaitGroup
  11. wg.Add(3)
  12. go func() {
  13. for num := range chang1 {
  14. fmt.Println(&quot;g1&quot;, num)
  15. }
  16. wg.Done()
  17. }()
  18. go func() {
  19. for num := range chang2 {
  20. fmt.Println(&quot;g2&quot;, num)
  21. }
  22. wg.Done()
  23. }()
  24. go func() {
  25. for num := range chang3 {
  26. fmt.Println(&quot;g3&quot;, num)
  27. }
  28. wg.Done()
  29. }()
  30. channels := []chan int{chang1, chang2, chang3}
  31. for i := 1; i &lt;= 10; i++ {
  32. currentCh := (i - 1) % 3
  33. channels[currentCh] &lt;- i
  34. }
  35. close(chang1)
  36. close(chang2)
  37. close(chang3)
  38. wg.Wait()
  39. }

output (with incorrect sequence)

g1- 1<br>
g1- 4<br>
g2- 2<br>
g3- 3<br>
g1- 7<br>
g2- 5<br>
g2- 8<br>
g3- 6<br>
g3- 9<br>
g1- 10<br>
...

答案1

得分: 2

如果你不想使用切片,我认为像这样的代码可以工作:- (playground)

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. func main() {
  6. chang1 := make(chan string)
  7. chang2 := make(chan string)
  8. chang3 := make(chan string)
  9. channels := []chan string{chang1, chang2, chang3}
  10. for i := 1; i < 10; i += 3 {
  11. go g1(i, channels[i%3])
  12. go g2(i+1, channels[(i+1)%3])
  13. go g3(i+2, channels[(i+2)%3])
  14. fmt.Print(<-channels[i%3])
  15. fmt.Print(<-channels[(i+1)%3])
  16. fmt.Print(<-channels[(i+2)%3])
  17. }
  18. }
  19. func g1(i int, chanel chan string) {
  20. chanel <- fmt.Sprintln("g1", i)
  21. }
  22. func g2(i int, chanel chan string) {
  23. chanel <- fmt.Sprintln("g2", i)
  24. }
  25. func g3(i int, chanel chan string) {
  26. chanel <- fmt.Sprintln("g3", i)
  27. }

输出结果:
g1 1
g2 2
g3 3
g1 4
g2 5
g3 6
g1 7
g2 8
g3 9

但请记住,在这个解决方案中,你需要运行3个 goroutine,然后等待它们全部给出结果,然后再继续执行。

如果这对你来说不可行,你需要使用带缓冲的通道。

英文:

if you don't want to use slice then I think something like this will work:- (playground)

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. )
  5. func main() {
  6. chang1 := make(chan string)
  7. chang2 := make(chan string)
  8. chang3 := make(chan string)
  9. channels := []chan string{chang1, chang2, chang3}
  10. for i := 1; i &lt; 10; i += 3 {
  11. go g1(i, channels[i%3])
  12. go g2(i+1, channels[(i+1)%3])
  13. go g3(i+2, channels[(i+2)%3])
  14. fmt.Print(&lt;-channels[i%3])
  15. fmt.Print(&lt;-channels[(i+1)%3])
  16. fmt.Print(&lt;-channels[(i+2)%3])
  17. }
  18. }
  19. func g1(i int, chanel chan string) {
  20. chanel &lt;- fmt.Sprintln(&quot;g1&quot;, i)
  21. }
  22. func g2(i int, chanel chan string) {
  23. chanel &lt;- fmt.Sprintln(&quot;g2&quot;, i)
  24. }
  25. func g3(i int, chanel chan string) {
  26. chanel &lt;- fmt.Sprintln(&quot;g3&quot;, i)
  27. }
  1. output
  2. g1 1
  3. g2 2
  4. g3 3
  5. g1 4
  6. g2 5
  7. g3 6
  8. g1 7
  9. g2 8
  10. g3 9

but keep in mind in this solution you have to run 3 goroutines then wait for all of them to give the result then go back

if this is not ok for you you need to use bufferd channels.

huangapple
  • 本文由 发表于 2022年2月17日 20:22:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/71158069.html
匿名

发表评论

匿名网友

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

确定