致命错误:所有goroutine都处于休眠状态 – 死锁!错误GO

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

fatal error: all goroutines are asleep - deadlock! error GO

问题

我是你的中文翻译助手,以下是你提供的代码的翻译:

我对Go语言中的并发编程还不熟悉,所以我尝试了一个使用通道和goroutine的示例。我想要实现生产者-消费者模式。生产者函数会不断生成随机字符串,而消费者函数会将它们转换为大写。我希望它在有限的时间内运行(2秒)。

package main

import (
	"fmt"
	"math/rand"
	"strings"
	"time"
)

func producer(x []string, c chan string) {
	i := 1
	for i > 0 {
		randomIndex := rand.Intn(len(x))
		pick := x[randomIndex]
		c <- pick
	}
}

func consumer(x string, c chan string) {
	x1 := strings.ToUpper(x)
	c <- x1
}

func main() {

	s := []string{"one", "two", "three", "four"}
	c1 := make(chan string)
	d1 := make(chan string)
	go producer(s, c1)
	go consumer(<-c1, d1)

	stop := time.After(2000 * time.Millisecond)
	for {
		select {
		case <-stop:
			fmt.Println("STOP AFTER 2 SEC!")
			return
		default:
			fmt.Println(<-d1)
			time.Sleep(50 * time.Millisecond)
		}
	}
}

我只得到了一个数组元素和一些错误。需要做哪些更改才能使这个示例正常工作?

输出:

TWO

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

goroutine 6 [chan send]:
main.producer({0xc00004e040, 0x4, 0x0?}, 0x0?)
created by main.main
exit status 2

英文:

I'm new to concurrency in Go so I tried an example with channels and goroutines. I want to have the producer-consumer pattern. The producer function forever gives random strings and the consumer modifies them by making them uppercase. I want to run it for a limited time(2 sec).

package main

import (
	&quot;fmt&quot;
	&quot;math/rand&quot;
	&quot;strings&quot;
	&quot;time&quot;
)

func producer(x []string, c chan string) {
	i := 1
	for i &gt; 0 {
		randomIndex := rand.Intn(len(x))
		pick := x[randomIndex]
		c &lt;- pick
	}
}

func consumer(x string, c chan string) {
	x1 := strings.ToUpper(x)
	c &lt;- x1
}

func main() {

	s := []string{&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;}
	c1 := make(chan string)
	d1 := make(chan string)
	go producer(s, c1)
	go consumer(&lt;-c1, d1)

	stop := time.After(2000 * time.Millisecond)
	for {
		select {
		case &lt;-stop:
			fmt.Println(&quot;STOP AFTER 2 SEC!&quot;)
			return
		default:
			fmt.Println(&lt;-d1)
			time.Sleep(50 * time.Millisecond)
		}
	}
}

I'm getting only one array element and some errors. What changes need to be made so this example would work?

OUTPUT:

TWO

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan receive]:
main.main()

goroutine 6 [chan send]:
main.producer({0xc00004e040, 0x4, 0x0?}, 0x0?)
created by main. main
exit status 2

答案1

得分: 1

你的消费者应该在一个循环中运行,这已经提到过了。

将消费者的第一个参数更改为chan string,而不是一个字符串。这样,生产者可以持续向该通道写入数据,供消费者在另一个通道上发布,直到时间限制到期。

func consumer(consumeChan chan string, outCh chan string) {
	for {
		select {
		case s := <-consumeChan:
			s = strings.ToUpper(s)
			outCh <- s
		}
	}
}

现在,在main函数中,在调用go consumer()之前,你正在等待来自生产者的c1通道的第一个响应。而不是这样做,将c1通道作为第一个参数传递。

func main() {
	s := []string{"one", "two", "three", "four"}
	c1 := make(chan string)
	d1 := make(chan string)
	go producer(s, c1)
	go consumer(c1, d1)

	stop := time.After(2000 * time.Millisecond)
	for {
		select {
		case <-stop:
			fmt.Println("STOP AFTER 2 SEC!")
			return
		case response := <-d1:
			fmt.Println(response)
			time.Sleep(50 * time.Millisecond)
		}
	}
}

这样应该会在c1通道上连续写入随机数字,消费者会将文本转换为大写并在d1通道上连续写入,直到2秒时间到。

英文:

Your consumer should run in a loop, this has been mentioned already.

Change the first parameter of the consumer so that it is a chan string instead of a string. That way the producer can continuously write to this channel for the consumer to publish on another channel until the time limit expires.

func consumer(consumeChan chan string, outCh chan string) {
	for {
		select {
		case s := &lt;- consumeChan:
			s = strings.ToUpper(s)
			outCh &lt;- s
		}
	}
}

Right now in the main func before go consumer() is called you are waiting for the first response to the c1 channel from the producer. Instead of doing that pass in the c1 channel as the first parameter.

func main() {
	s := []string{&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;}
	c1 := make(chan string)
	d1 := make(chan string)
	go producer(s, c1)
	go consumer(c1, d1)

	stop := time.After(2000 * time.Millisecond)
	for {
		select {
		case &lt;-stop:
			fmt.Println(&quot;STOP AFTER 2 SEC!&quot;)
			return
		case response := &lt;- d1:
			fmt.Println(response)
			time.Sleep(50 * time.Millisecond)
		}
	}
}

This should show you continuous writes of random numbers by the producer on the c1 channel, and continuous writes on the d1 channel by the consumer with the text in all uppercase until the 2 seconds is up.

huangapple
  • 本文由 发表于 2022年11月28日 02:46:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/74592837.html
匿名

发表评论

匿名网友

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

确定