Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/gwt/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么会出现致命错误:所有goroutine都处于休眠状态-死锁!在这个代码中?_Go - Fatal编程技术网

为什么会出现致命错误:所有goroutine都处于休眠状态-死锁!在这个代码中?

为什么会出现致命错误:所有goroutine都处于休眠状态-死锁!在这个代码中?,go,Go,这是参考Go编程语言中的以下代码-第8章第238页,从下面的链接复制 如果我尝试运行上述代码,它会给出: 等待重置 3547 2793 致命错误:所有goroutine都处于休眠状态-死锁 为什么在上面出现了僵局?仅供参考,在调用makeThumbnail6的方法中,我确实关闭了文件名通道您的通道是无缓冲的(在生成()通道时,您没有指定任何缓冲区大小)。这意味着对通道的写入会一直阻塞,直到写入的值被读取为止。在调用wg.Wait()之后,您从通道中读取数据,因此不会读取任何内容,并且所有的gor

这是参考Go编程语言中的以下代码-第8章第238页,从下面的链接复制

如果我尝试运行上述代码,它会给出:

等待重置
3547
2793
致命错误:所有goroutine都处于休眠状态-死锁


为什么在上面出现了僵局?仅供参考,在调用
makeThumbnail6
的方法中,我确实关闭了
文件名
通道

您的通道是无缓冲的(在生成()通道时,您没有指定任何缓冲区大小)。这意味着对通道的写入会一直阻塞,直到写入的值被读取为止。在调用wg.Wait()之后,您从通道中读取数据,因此不会读取任何内容,并且所有的goroutine都会被阻塞写入

也就是说,这里不需要WaitGroup。当您不知道goroutine何时完成时,WaitGroups是很好的,但是您正在返回结果,所以您知道。下面是一个示例代码,它执行的操作与您尝试执行的操作(使用假工作负载)类似

主程序包
进口(
“fmt”
“时间”
)
func main(){
var procs int=0
文件名:=[]字符串{“file1”、“file2”、“file3”、“file4”}
mychan:=make(chan字符串)
对于uf:=范围文件名{
进程+=1
//工人
go func(f字符串){
fmt.Printf(“工人处理%v\n”,f)
时间。睡眠(时间。秒)

mychan虽然问题提出已经有一段时间了,但我遇到了同样的问题。最初我的主要观点如下:

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)}
func main(){
文件名:=make(chan字符串,len(os.Args))
对于uf:=范围os.Args[1:]{

文件名代码是错误的。简言之,通道
大小
是无缓冲的。要修复它,我们需要在创建
大小
时使用具有足够容量的缓冲通道。一个线性修复就足够了,如图所示。这里我只是简单地假设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
}
func makeThumbnails6(文件名和字符串)int64{
大小:=make(chan int641024)//更改
var wg sync.WaitGroup//工作goroutine的数量
对于f:=范围文件名{
工作组.添加(1)
//工人
go func(f字符串){
推迟工作组完成()
thumb,err:=缩略图.ImageFile(f)
如果错误!=零{
log.Println(错误)
回来
}
info,:=os.Stat(thumb)//确定忽略错误
fmt.Println(info.Size())

大小太好了!当我添加一个缓冲区时是的,比如
size:=make(chan int64,10)
那么代码就可以工作了。谢谢你,疯了!呃……只有当你的有效负载数少于10时,它才会工作。这很脆弱。我强烈建议你像我发布的代码示例那样使用非阻塞读取。是的,我理解这一点,但它帮助我理解为什么会出现死锁。同意在实践中我会使用你共享的代码或他在书中写了一个:)谢谢。我不知道如何调用这个函数。
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)
        }
    }
}
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)}
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
}