在Go函数通道中的死锁问题

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

Deadlock in go function channel

问题

为什么即使我只从通道中传递一个值并获得一个输出,仍然会出现死锁?

package main

import "fmt"
import "math/cmplx"

func max(a []complex128, base int, ans chan float64, index chan int) {
   
    fmt.Printf("called for %d,%d\n",len(a),base)
    
    maxi_i := 0
    maxi := cmplx.Abs(a[maxi_i]);

    for i:=1 ; i< len(a) ; i++ {
        if cmplx.Abs(a[i]) > maxi {
            maxi_i = i
            maxi = cmplx.Abs(a[i])
        }
    }
    
    fmt.Printf("called for %d,%d and found %f %d\n",len(a),base,maxi,base+maxi_i)
    
    ans <- maxi
    index <- base+maxi_i
}

func main() {
    ans := make([]complex128,128)
    
    numberOfSlices := 4
    incr := len(ans)/numberOfSlices
    tmp_val := make([]chan float64,numberOfSlices)
    tmp_index := make([]chan int,numberOfSlices)
    for i,j := 0 , 0; i < len(ans); j++{
        fmt.Printf("From %d to %d - %d\n",i,i+incr,len(ans))
        go max(ans[i:i+incr],i,tmp_val[j],tmp_index[j])

        i = i+ incr
    }
//After Here is it stops deadlock
    maximumFreq := <- tmp_index[0]
    maximumMax := <- tmp_val[0]
    for i := 1; i < numberOfSlices; i++ {

        tmpI := <- tmp_index[i]
        tmpV := <- tmp_val[i]

        if(tmpV > maximumMax ) {
            maximumMax = tmpV
            maximumFreq = tmpI
        }
    }

    fmt.Printf("Max freq = %d",maximumFreq)
    
}
英文:

Why is there a deadlock even tho I just pass one and get one output from the channel?

package main

import &quot;fmt&quot;
import &quot;math/cmplx&quot;

func max(a []complex128, base int, ans chan float64,  index chan int) {
   
    fmt.Printf(&quot;called for %d,%d\n&quot;,len(a),base)
    
    maxi_i := 0
    maxi := cmplx.Abs(a[maxi_i]);

    for i:=1 ; i&lt; len(a) ; i++ {
        if cmplx.Abs(a[i]) &gt; maxi {
            maxi_i = i
            maxi = cmplx.Abs(a[i])
        }
    }
    
    fmt.Printf(&quot;called for %d,%d and found %f %d\n&quot;,len(a),base,maxi,base+maxi_i)
    
    ans &lt;- maxi
    index &lt;- base+maxi_i
}

func main() {
    ans := make([]complex128,128)
    
    numberOfSlices := 4
    incr := len(ans)/numberOfSlices
    tmp_val := make([]chan float64,numberOfSlices)
    tmp_index := make([]chan int,numberOfSlices)
    for i,j := 0 , 0; i &lt; len(ans); j++{
        fmt.Printf(&quot;From %d to %d - %d\n&quot;,i,i+incr,len(ans))
        go max(ans[i:i+incr],i,tmp_val[j],tmp_index[j])

        i = i+ incr
    }
//After Here is it stops deadlock
    maximumFreq := &lt;- tmp_index[0]
    maximumMax := &lt;- tmp_val[0]
    for i := 1; i &lt; numberOfSlices; i++ {

        tmpI := &lt;- tmp_index[i]
        tmpV := &lt;- tmp_val[i]

        if(tmpV &gt; maximumMax ) {
            maximumMax = tmpV
            maximumFreq = tmpI
        }
    }

    fmt.Printf(&quot;Max freq = %d&quot;,maximumFreq)
    
}

答案1

得分: 2

对于阅读这个问题并且可能想知道为什么他的代码在这里失败的人,这里有一个解释。

当他像这样构建他的通道切片时:

tmp_val := make([]chan float64,numberOfSlices)

他创建了一个通道切片,其中每个索引都是通道的零值。通道的零值是nil,因为通道是引用类型,一个nil通道会永远阻塞发送操作,而且由于nil通道中从来没有任何东西,它也会永远阻塞接收操作。因此,你会得到一个死锁。

当footy将他的代码更改为使用循环逐个构建每个通道时:

tmp_val[i] = make(chan float64)

他构建了非nil通道,一切都很好。

英文:

For those reading this question and perhaps wondering why his code failed here's an explanation.

When he constructed his slice of channels like so:

tmp_val := make([]chan float64,numberOfSlices)

He made slice of channels where every index was to the channels zero value. A channels zero value is nil since channels are reference types and a nil channel blocks on send forever and since there is never anything in a nil channel it will also block on recieve forever. Thus you get a deadlock.

When footy changes his code to construct each channel individually using

tmp_val[i] = make(chan float64)

in a loop he constructs non-nil channels and everything is good.

答案2

得分: 1

我在制作chan时犯了错误。应该这样做

numberOfSlices := 4
incr := len(ans)/numberOfSlices
var tmp_val [4]chan float64
var tmp_index [4]chan int

for i := range tmp_val {
    tmp_val[i] = make(chan float64)
    tmp_index[i] = make(chan int)
}

for i,j := 0 , 0; i < len(ans); j++{
    fmt.Printf("从 %d 到 %d [j:%d] - %d\n",i,i+incr,j,len(ans))
    go maximumFunc(ans[i:i+incr],i,tmp_val[j],tmp_index[j])

    i = i+ incr
}
英文:

I was wrong in making of the chan. Should have done

numberOfSlices := 4
incr := len(ans)/numberOfSlices
var tmp_val [4]chan float64
var tmp_index [4]chan int

for i := range tmp_val {
    tmp_val[i] = make(chan float64)
    tmp_index[i] = make(chan int)
}

for i,j := 0 , 0; i &lt; len(ans); j++{
    fmt.Printf(&quot;From %d to %d [j:%d] - %d\n&quot;,i,i+incr,j,len(ans))
    go maximumFunc(ans[i:i+incr],i,tmp_val[j],tmp_index[j])

    i = i+ incr
}

huangapple
  • 本文由 发表于 2013年5月17日 06:11:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/16598353.html
匿名

发表评论

匿名网友

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

确定