我有一个输入数字的基本频道 稍后通过公式修改自身 有3个通道可以根据不同情况接收值 发送次数的平均值必须介于两个值之间,如if循环所示
if average < 10 {
channel <- average
}
if average > 0 && average < 100 {
channel1 <- average
}
if average > 75 && average < 200 {
channel2 <- average
}
我面临的问题是在避免死锁的情况下,我必须做一个奇怪的if循环,该循环读取所有已发送的值,但从不读取
之所以发生这种情况,是因为 averageisOK 全局值变为false,但是至少还有2个值仍在等待读取,或者也许这就是我的理解。
因此有可能避免奇怪的循环并对此有更好的解决方案。
package main
import(
"fmt"
"sync"
)
var wait sync.WaitGroup
var averageIsOk = true
var doneSendersCount = 0
var counterIsDone = false
func main() {
counterChannel := make(chan float64)
channel := make(chan float64)
channel1 := make(chan float64)
channel2 := make(chan float64)
for i := 0; i < 10; i++ {
wait.Add(1)
go send(counterChannel, float64(i))
}
wait.Add(1)
go count(counterChannel, channel, channel1, channel2)
wait.Add(1)
go print(channel, 1)
wait.Add(1)
go print(channel1, 2)
wait.Add(1)
go print(channel2, 3)
wait.Wait()
}
func send (counterChannel chan<- float64, startNumber float64){
defer wait.Done()
i := startNumber
for averageIsOk {
counterChannel <- i
i = i * i - 4 * i + 1
}
doneSendersCount++
}
func count (counterChannel <-chan float64, channel chan<- float64, channel1 chan<- float64, channel2 chan<- float64){
defer wait.Done()
var averageArray [15]float64
for i := 0; i < 15; i++ {
averageArray[i] = 0
}
for averageIsOk {
receivedNumber := <- counterChannel
for i := 14; i > 0; i-- {
averageArray[i] = averageArray[i - 1]
}
averageArray[0] = receivedNumber
average := 0.0
for i := 0; i < 15; i++ {
average += averageArray[i]
}
average = average / 15
if average < 10 {
channel <- average
}
if average > 0 && average < 100 {
channel1 <- average
}
if average > 75 && average < 200 {
channel2 <- average
}
if average > 200 {
close(channel)
close(channel1)
close(channel2)
averageIsOk = false
}
}
counterIsDone = true
for doneSendersCount != 10 {
select {
case <- counterChannel:
break
default:
break
}
}
}
func print (printChannel <-chan float64, printerNumber int){
defer wait.Done()
for averageIsOk {
receivedNumber := <- printChannel
fmt.Println("Kanalas nr-", printerNumber, ":", receivedNumber)
}
for !counterIsDone {
select {
case <- printChannel:
break
default:
break
}
}
}