并发执行但序列化输出

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

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:

package main

import (
	"fmt"
	"sync"
)

func main() {

	chang1 := make(chan int)
	chang2 := make(chan int)
	chang3 := make(chan int)

	var wg sync.WaitGroup
	wg.Add(3)

	go func() {
		for num := range chang1 {
			fmt.Println("g1", num)
		}
		wg.Done()
	}()

	go func() {
		for num := range chang2 {
			fmt.Println("g2", num)
		}
		wg.Done()

	}()

	go func() {
		for num := range chang3 {
			fmt.Println("g3", num)
		}
		wg.Done()

	}()

	channels := []chan int{chang1, chang2, chang3}

	for i := 1; i <= 10; i++ {

		currentCh := (i - 1) % 3
		channels[currentCh] <- i

	}

	close(chang1)
	close(chang2)
	close(chang3)
	wg.Wait()

}

输出(顺序不正确)

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:

package main

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

func main() {

	chang1 := make(chan int)
	chang2 := make(chan int)
	chang3 := make(chan int)

	var wg sync.WaitGroup
	wg.Add(3)

	go func() {
		for num := range chang1 {
			fmt.Println(&quot;g1&quot;, num)
		}
		wg.Done()
	}()

	go func() {
		for num := range chang2 {
			fmt.Println(&quot;g2&quot;, num)
		}
		wg.Done()

	}()

	go func() {
		for num := range chang3 {
			fmt.Println(&quot;g3&quot;, num)
		}
		wg.Done()

	}()

	channels := []chan int{chang1, chang2, chang3}

	for i := 1; i &lt;= 10; i++ {

		currentCh := (i - 1) % 3
		channels[currentCh] &lt;- i

	}

	close(chang1)
	close(chang2)
	close(chang3)
	wg.Wait()

}

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)

package main

import (
	"fmt"
)

func main() {

	chang1 := make(chan string)
	chang2 := make(chan string)
	chang3 := make(chan string)

	channels := []chan string{chang1, chang2, chang3}

	for i := 1; i < 10; i += 3 {

		go g1(i, channels[i%3])
		go g2(i+1, channels[(i+1)%3])
		go g3(i+2, channels[(i+2)%3])

		fmt.Print(<-channels[i%3])
		fmt.Print(<-channels[(i+1)%3])
		fmt.Print(<-channels[(i+2)%3])
	}

}

func g1(i int, chanel chan string) {

	chanel <- fmt.Sprintln("g1", i)

}

func g2(i int, chanel chan string) {

	chanel <- fmt.Sprintln("g2", i)

}

func g3(i int, chanel chan string) {

	chanel <- fmt.Sprintln("g3", i)

}

输出结果:
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)

package main

import (
	&quot;fmt&quot;
)

func main() {

	chang1 := make(chan string)
	chang2 := make(chan string)
	chang3 := make(chan string)

	channels := []chan string{chang1, chang2, chang3}

	for i := 1; i &lt; 10; i += 3 {

		go g1(i, channels[i%3])
		go g2(i+1, channels[(i+1)%3])
		go g3(i+2, channels[(i+2)%3])

		fmt.Print(&lt;-channels[i%3])
		fmt.Print(&lt;-channels[(i+1)%3])
		fmt.Print(&lt;-channels[(i+2)%3])
	}

}

func g1(i int, chanel chan string) {

	chanel &lt;- fmt.Sprintln(&quot;g1&quot;, i)

}

func g2(i int, chanel chan string) {

	chanel &lt;- fmt.Sprintln(&quot;g2&quot;, i)

}

func g3(i int, chanel chan string) {

	chanel &lt;- fmt.Sprintln(&quot;g3&quot;, i)

}
output 
g1 1
g2 2
g3 3
g1 4
g2 5
g3 6
g1 7
g2 8
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:

确定