如何重叠goroutines?

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

How can I overlap goroutines?

问题

我有三个goroutine,它们应该以某种循环方式工作。例如,我有以下代码:

go first() {
	// 做一些事情
}
 
go second() {
	// 做另一种事情
}

go third() {
	// 做第三种事情
} 

它们应该按照以下顺序工作:
First - second - third - first - /以此类推/

我猜我需要使用通道来实现,但我无法找到正确的方法。如果我创建三个不同的通道
FirstToSecond
SeocndToThird
ThirdToFirst,然后运行程序时,我会得到错误:

fatal error: all goroutines are asleep - deadlock!

但是,如果我去掉ThirdToFirst,我就有一个正确的循环,然后goroutine开始随机工作。

我肯定漏掉了什么,但是是什么呢?

以下是带有两个goroutine的示例代码:

package main

import (
	"fmt"
	"sync"
)

func main() {
	var wg sync.WaitGroup
	wg.Add(2)

	ch1 := make(chan struct{})
	ch2 := make(chan struct{})

	go func() {
		for _, value := range []int{1, 3, 5} {
			<- ch1
			fmt.Println(value)
			ch2 <- struct{}{}	 
		} 
		wg.Done()
	}()

	go func() {
		for _, value := range []int{2, 4, 6} {
			<- ch2
			fmt.Println(value)
			ch1 <- struct{}{}
		} 
		wg.Done()
	}()

	wg.Wait()
}
英文:

I have three gorutines, which should work in some sort of loop. For example, I have

go first() {
	// do some stuff
}
 
go second() {
	// do another kind of stuff
}

go third() {
	// do third kind of stuff
} 

And they have to work like that:
First - second - third - first - /and so on and so on/

I guess I have to use channels fo that, but I can't figure out proper way to do so.
If I make three different channels
FirstToSecond,
SeocndToThird,
ThirdToFirst, then when I run a program, I get error:

fatal error: all goroutines are asleep - deadlock!

But if I get rid of ThirdToFirst, I have one proper loop, and then gorutines start to work randomly.

I'm certainly missing something, but what?

Example code with two gorutines

package main

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

func main() {
	var wg sync.WaitGroup
	wg.Add(2)

	ch1 := make(chan struct{})
	ch2 := make(chan struct{})

	go func() {
		for _, value := range []int{1, 3, 5} {
			&lt;- ch1
			fmt.Println(value)
			ch2 &lt;- struct{}{}	 
		} 
		wg.Done()
	}()

	go func() {
		for _, value := range []int{2, 4, 6} {
			&lt;- ch2
			fmt.Println(value)
			ch1 &lt;- struct{}{}
		} 
		wg.Done()
	}()

	wg.Wait()
}

答案1

得分: 1

如果您需要这样的顺序执行,您可能需要重新评估使用goroutine的需求。然而,您描述的解决方案是正确的:

go first() {
  for {
    <-ch1
    // 做一些事情
    ch2<-struct{}{}
  } 
}()

go second() {
  for {
    <-ch2
    // 做一些事情
    ch3<-struct{}{}
  } 
}()

go third() {
  for {
    <-ch3
    // 做一些事情
    ch1<-struct{}{}
  } 
}()

然而,这是一个循环设置,您必须在此结构之外启动第一个:

go first() {...}()
go second() {...}()
go third() {...}()

// 启动第一个
ch1<-struct{}{}
英文:

If you need such sequencing, you might reevaluate your need to use goroutines. However, the way you described the solution is correct:

go first() {
  for {
    &lt;-ch1
    // do stuff
    ch2&lt;-struct{}{}
  } 
}()

go second() {
  for {
    &lt;-ch2
    // do stuff
    ch3&lt;-struct{}{}
  } 
}()

go third() {
  for {
    &lt;-ch3
    // do stuff
    ch1&lt;-struct{}{}
  } 
}()

However, this is a circular setup, and you have to start the first one outside this structure:

go first() {...}()
go second() {...}()
go third() {...} ()

// Start the first one
ch1&lt;-struct{}{}

huangapple
  • 本文由 发表于 2021年7月31日 01:20:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/68594864.html
匿名

发表评论

匿名网友

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

确定