3 回答
TA贡献1942条经验 获得超3个赞
您的频道是无缓冲的(您在 make()ing 频道时没有指定任何缓冲区大小)。这意味着写入通道会阻塞,直到写入的值被读取。在调用 wg.Wait() 之后,您从通道读取数据,因此不会读取任何内容,并且您的所有 goroutine 都会卡在阻塞写入中。
也就是说,您在这里不需要 WaitGroup。当您不知道 goroutine 何时完成时,WaitGroups 很有用,但您正在发回结果,所以您知道。这是一个示例代码,它执行与您尝试执行的操作类似的操作(使用伪造的工作负载)。
package main
import (
"fmt"
"time"
)
func main() {
var procs int = 0
filenames := []string{"file1", "file2", "file3", "file4"}
mychan := make(chan string)
for _, f := range filenames {
procs += 1
// worker
go func(f string) {
fmt.Printf("Worker processing %v\n", f)
time.Sleep(time.Second)
mychan <- f
}(f)
}
for i := 0; i < procs; i++ {
select {
case msg := <-mychan:
fmt.Printf("got %v from worker channel\n", msg)
}
}
}
TA贡献1847条经验 获得超7个赞
虽然提出问题已经有一段时间了,但我遇到了同样的问题。最初我的主要内容如下所示:
func main() {
filenames := make(chan string, len(os.Args))
for _, f := range os.Args[1:] {
filenames <- f
}
sizes := makeThumbnails6(filenames)
close(filenames)
log.Println("Total size: ", sizes)}
此版本死锁,因为调用range filenames是makeThumbnails6同步的,因此close(filenames)in main 从未被调用。输入的通道makeThumbnails6是无缓冲的,因此 goroutines 在尝试发回大小时会阻塞。
close(filenames)解决方案是在 main 中进行函数调用之前移动。
TA贡献1854条经验 获得超8个赞
代码错误。简而言之,通道sizes是无缓冲的。要修复它,我们需要在创建时使用具有足够容量的缓冲通道sizes。一行修复就足够了,如图所示。这里我只是做了一个简单的假设,1024足够大。
func makeThumbnails6(filenames chan string) int64 {
sizes := make(chan int64, 1024) // CHANGE
var wg sync.WaitGroup // number of working goroutines
for f := range filenames {
wg.Add(1)
// worker
go func(f string) {
defer wg.Done()
thumb, err := thumbnail.ImageFile(f)
if err != nil {
log.Println(err)
return
}
info, _ := os.Stat(thumb) // OK to ignore error
fmt.Println(info.Size())
sizes <- info.Size()
}(f)
}
// closer
go func() {
wg.Wait()
close(sizes)
}()
var total int64
for size := range sizes {
total += size
}
return total
}
- 3 回答
- 0 关注
- 130 浏览
添加回答
举报