gpt4 book ai didi

multithreading - Go 线程死锁错误 - go 例程的正确使用方法是什么?

转载 作者:IT王子 更新时间:2023-10-29 01:53:17 25 4
gpt4 key购买 nike

我正在编写一个根据用户输入计算黎曼和的程序。该程序会将函数拆分为 1000 个矩形(是的,我知道我还没有在那里进行数学运算)并对它们求和并返回答案。我正在使用 go routines 来计算 1000 个矩形但是我得到了一个

fatal error: all go routines are asleep - deadlock!

处理多个go例程的正确方法是什么?我一直在环顾四周,没有看到与我的情况相似的例子?我是新手,想遵守标准。这是我的代码(如果你想看看它的典型用例是什么,它是可运行的 - 但它确实会中断)

package main

import "fmt"
import "time"

//Data type to hold 'part' of function; ie. "4x^2"
type Pair struct {
coef, exp int
}

//Calculates the y-value of a 'part' of the function and writes this to the channel
func calc(c *chan float32, p Pair, x float32) {
val := x

//Raise our x value to the power, contained in 'p'
for i := 1; i < p.exp; i++ {

val = val * val
}

//Read existing answer from channel
ans := <-*c

//Write new value to the channel
*c <- float32(ans + (val * float32(p.coef)))
}

var c chan float32 //Channel
var m map[string]Pair //Map to hold function 'parts'

func main() {

c = make(chan float32, 1001) //Buffered at 1001
m = make(map[string]Pair)
var counter int
var temp_coef, temp_exp int
var check string
var up_bound, low_bound float32
var delta float32

counter = 1
check = "default"

//Loop through as long as we have no more function 'parts'
for check != "n" {

fmt.Print("Enter the coefficient for term ", counter, ": ")
fmt.Scanln(&temp_coef)

fmt.Print("Enter the exponent for term ", counter, ": ")
fmt.Scanln(&temp_exp)

fmt.Print("Do you have more terms to enter (y or n): ")
fmt.Scanln(&check)

fmt.Println("")

//Put data into our map
m[string(counter)] = Pair{temp_coef, temp_exp}

counter++
}

fmt.Print("Enter the lower bound: ")
fmt.Scanln(&low_bound)

fmt.Print("Enter the upper bound: ")
fmt.Scanln(&up_bound)

//Calculate the delta; ie. our x delta for the riemann sum
delta = (float32(up_bound) - float32(low_bound)) / float32(1000)

//Make our go routines here to add
for i := low_bound; i < up_bound; i = i + delta {

//'counter' is indicative of the number of function 'parts' we have
for j := 1; j < counter; j++ {

//Go routines made here
go calc(&c, m[string(j)], i)
}

}

//Wait for the go routines to finish
time.Sleep(5000 * time.Millisecond)

//Read the result?
ans := <-c

fmt.Print("Answer: ", ans)
}

最佳答案

它死锁是因为 calc()main() 函数都在任何人写入之前从 channel 中读取数据。

所以你最终会在每个(非主要的)go 例程中阻塞:

ans := <-*c

等待其他人将值输入 channel 。因此,他们都没有到达他们实际写入 channel 的下一行。 main() 例程将阻塞在:

ans := <-c

大家都在等待=死锁

使用缓冲 channel

您的解决方案应该让 calc() 函数只写入 channel ,而 main() 可以在 for-range< 中从中读取 循环,总结来自 go-routines 的值。

您还需要为 main() 添加一种方法来知道何时没有更多的值到达,也许通过使用 sync.WaitGroup(也许不是最好的,因为 main 不应该等待而是总结)或一个普通的计数器。

使用共享内存

有时它不一定是您需要的 channel 。拥有一个共享值,您可以使用 sync/atomic 更新 (原子添加不适用于 float )并使用 sync.Mutex 锁定也能正常工作。

关于multithreading - Go 线程死锁错误 - go 例程的正确使用方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23530611/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com