Go:所有的goroutine都处于休眠状态-死锁

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

Go: all goroutines are asleep - deadlock

问题

这段代码的问题可能出在goroutine的使用上。根据输出信息,所有的goroutine都处于休眠状态,导致死锁。可能的原因是goroutine没有正确地接收到通道的值。

proccesFileName函数中,你应该将filename作为参数传递给匿名函数,而不是在循环中直接使用。这样可以确保每个goroutine都使用不同的filename值。

修改后的代码如下:

for _, filename := range file_names {
	go func(filename string) {
		proccesFileName(filename, c, ce)
	}(filename)
}

这样修改后,每个goroutine都会接收到不同的filename值,避免了竞争条件和死锁问题。

另外,你还可以考虑使用sync.WaitGroup来等待所有的goroutine完成任务,以避免使用无限循环和死锁的问题。具体的实现方式可以参考Go语言的官方文档中关于sync包的介绍。

希望这些信息对你有帮助!如果还有其他问题,请随时提问。

英文:

<br>
I have snippet of code to resizing images.
<br>
I'm using resize lib.
<br>
Here is the snippet:

package main

import (
	&quot;fmt&quot;
	&quot;github.com/nfnt/resize&quot;
	&quot;image&quot;
	&quot;image/jpeg&quot;
	&quot;os&quot;
	&quot;runtime&quot;
)

func main() {
	runtime.GOMAXPROCS(4)

	file_names := make([]string, 5)
	for i := 1; i &lt; 6; i++ {
		file_names[i-1] = fmt.Sprintf(&quot;%v&quot;, i)
	}

	c := make(chan string)
	ce := make(chan error)

	for _, filename := range file_names {
		go func() {
			proccesFileName(filename, c, ce)
		}()
	}

	for {
		select {
		case str := &lt;-c:
			fmt.Println(str)
			break
		case err := &lt;-ce:
			fmt.Println(err)
			break
		}
	}
}

And here is my proccesFileName function:

func proccesFileName(filename string, c chan string, ce chan error) {
	file, err := os.Open(fmt.Sprintf(&quot;in/%v.jpg&quot;, filename))
	if err != nil {
		ce &lt;- err
	}
	defer file.Close()

	img, err := jpeg.Decode(file)
	if err != nil {
		ce &lt;- err
	}

	scales := []float32{1.0, 0.8, 0.6, 0.5, 0.25, 0.01}
	thumbs := make([]image.Image, len(scales))
	for i := 0; i &lt; len(scales); i++ {
		thumbs[i] = resize.Resize(uint(float32(img.Bounds().Max.X)*scales[i]),
			uint(float32(img.Bounds().Max.Y)*scales[i]), img, resize.Lanczos3)

		thumb_name := fmt.Sprintf(&quot;out/%v_thumb_%v.jpg&quot;, filename, i+1)

		out, err := os.Create(thumb_name)
		if err != nil {
			ce &lt;- err
		}
		defer out.Close()

		jpeg.Encode(out, thumbs[i], nil)

		c &lt;- fmt.Sprintf(&quot;%v FINISHED&quot;, i)
	}
}

And I have the output:

0 FINISHED
0 FINISHED
0 FINISHED
0 FINISHED
0 FINISHED
1 FINISHED
1 FINISHED
1 FINISHED
2 FINISHED
1 FINISHED
1 FINISHED
2 FINISHED
3 FINISHED
2 FINISHED
2 FINISHED
2 FINISHED
3 FINISHED
4 FINISHED
4 FINISHED
3 FINISHED
5 FINISHED
3 FINISHED
5 FINISHED
3 FINISHED
4 FINISHED
4 FINISHED
4 FINISHED
5 FINISHED
5 FINISHED
5 FINISHED
fatal error: all goroutines are asleep - deadlock!

goroutine 16 [select]:
main.main()
	/home/cnaize/Desktop/test/main.go:30 +0x509

goroutine 19 [finalizer wait]:
runtime.park(0x413ee0, 0x5b2f70, 0x5b1a89)
	/usr/local/go/src/pkg/runtime/proc.c:1369 +0x89
runtime.parkunlock(0x5b2f70, 0x5b1a89)
	/usr/local/go/src/pkg/runtime/proc.c:1385 +0x3b
runfinq()
	/usr/local/go/src/pkg/runtime/mgc0.c:2644 +0xcf
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445
exit status 2

Where may be the problem?

答案1

得分: 1

你不需要无限期地等待。你知道消息将会在这些通道上。

for _ = range file_names {
    select {
    case str := <-c:
        fmt.Println(str)
    case err := <-ce:
        fmt.Println(err)
    }
}
英文:

You need not to wait indefinitely. You know how messages will be on the channels.

for _ = range file_names {
    select {
    case str := &lt;-c
        fmt.Println(str)
    case err := &lt;-ce
        fmt.Println(err)
    }
}

huangapple
  • 本文由 发表于 2014年12月4日 21:02:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/27294769.html
匿名

发表评论

匿名网友

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

确定