英文:
calculate maximum in parallel in golang using go routine
问题
我正在尝试理解并发性和并行性。我需要使用Go协程、通道和等待组来计算数组的最大值,并将其存储在一个共享变量中。以下是你提供的代码,出现了死锁问题,请给予指导。
package main
import (
"fmt"
"math"
)
func main() {
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
max := math.MinInt32
ch := make(chan int)
for i := 0; i < len(arr); i++ {
go func(i int) {
ch <- arr[i]
}(i)
}
for i := 0; i < len(arr); i++ {
if max < <-ch {
max = <-ch
}
}
fmt.Println(max)
}
你的代码中出现死锁问题的原因是在第二个for循环中,你尝试从通道ch
中接收两次数据,而实际上只有一个goroutine向通道发送了数据。这导致第二次接收操作无法完成,从而导致死锁。
为了解决这个问题,你可以将接收操作的结果存储在一个临时变量中,然后再进行比较和更新最大值。修改后的代码如下:
package main
import (
"fmt"
"math"
"sync"
)
func main() {
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
max := math.MinInt32
ch := make(chan int)
var wg sync.WaitGroup
for i := 0; i < len(arr); i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
ch <- arr[i]
}(i)
}
go func() {
wg.Wait()
close(ch)
}()
for num := range ch {
if num > max {
max = num
}
}
fmt.Println(max)
}
在修改后的代码中,我们使用了sync.WaitGroup
来等待所有的goroutine完成发送操作,并使用close(ch)
来关闭通道。然后,我们使用range
循环从通道中接收数据,并进行比较和更新最大值。
这样修改后的代码应该能够正确计算数组的最大值,并避免死锁问题。
英文:
I am trying to understand concurrency and parallelism. I need to calculate the maximum of an array using the go routine, channel wait group, and stored in a shared variable here is the below code getting deadlock, please give direction
package main
import (
"fmt"
"math"
)
func main() {
arr := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
max := math.MinInt32
ch := make(chan int)
for i := 0; i < len(arr); i++ {
go func(i int) {
ch <- arr[i]
}(i)
}
for i := 0; i < len(arr); i++ {
if max < <-ch {
max = <-ch
}
}
fmt.Println(max)
}
答案1
得分: 4
第二个循环期望从ch
接收len(arr)*2
个值,而实际上只有len(arr)
个值被发送到了ch
中。
并且将返回通道中读取的下一个值,而不是最大值。
// 从通道中读取两次
if max << -ch {
// 这是最大值之后的下一个值,而不是最大值
max = << -ch
}
将第二个循环改为
for i := 0; i < len(arr); i++ {
got := << -ch
if max < got {
max = got
}
}
建议:这并不是并行计算最大值。这里的通道是串行读取的,并将值与最大值进行比较,与直接遍历切片本身没有太大区别。
相反,你可以实现基于DAC的方法,在一个go协程中找到2个元素的最大值,然后合并结果,找到最终的最大值。这将更好地学习通道和go协程之间的通信。
英文:
Second loop expects to receive len(arr)*2
values from ch
. while len(arr)
values are all thar are send to ch
And will return next value read from the channel for max but not max element.
// Reading from channel twice.
if max < <-ch {
// This is next value after max not max
max = <-ch
}
Change second loop to
for i := 0; i < len(arr); i++ {
got := <-ch
if max < got {
max = got
}
}
Suggest: this is not calculating maximum in parallel . Channel is read serially here and values compared to a max, as good as ranging over the slice itself.
You can instead implement DAC based approach to find max of 2 elements in a go-routine and then merge the results, to find the ultimate max. This will provide you better learning of channels and inter-go-routine communication
答案2
得分: 1
每次调用<-ch
时,您都会从通道中读取一个新值。这意味着您的代码
if max < <-ch {
max = <-ch
}
不会按照您的期望工作。
如果您的通道被提供了值1
,2
,...,那么您的代码将按照以下方式工作:
if max < <-ch { // 读取值`1`,将其与`max`进行比较
max = <-ch // 读取值`2`,然后将其赋给`max`
}
导致死锁的原因是您从通道中读取的值是写入它的值的两倍,因为对于每次循环,您尝试读取两个值。
为了同时解决这两个问题,可以使用一个临时变量:
for i := 0; i < len(arr); i++ {
if value := <-ch; max < value {
max = value
}
}
英文:
Every time you call <- ch
, you read a new value from the channel. This means that your code
if max < <-ch {
max = <-ch
}
Does not do what you expect.
If your channel is fed the values 1
, 2
, ..., then your code will work as follows:
if max < <-ch { // Reads value `1`, compares it against `max`
max = <-ch // Reads the value `2`, then assigns it to `max`
}
The reason this leads to a deadlock is that you're reading twice as many values from the channel as you write to it, since for every time through the loop, you're trying to read two values.
To solve both problems at once, use a temporary variable:
for i := 0; i < len(arr); i++ {
if value := <-ch; max < value {
max = value
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论