zoukankan      html  css  js  c++  java
  • Golang解决fatal error: all goroutines are asleep

    今天进行一个协程操作demo时总是报错

    //workerpool.go
    package main
    
    import (
    	"fmt"
    	"time"
    )
    
    //工作线程
    func workerPool(jobs <-chan int, results chan<- int) {
    	for j := range jobs {
    		fmt.Println("start job", j)
    		time.Sleep(time.Second) //模拟耗时工作
    		fmt.Println("finish job", j)
    		results <- j
    	}
    }
    
    func main() {
    	const numJobs = 5
    	jobs := make(chan int, numJobs)    //
    	results := make(chan int, numJobs) //
    
    	go workerPool(jobs, results)
    
    	for i := 1; i <= numJobs; i++ {
    		jobs <- i
    	}
            close(jobs)
            for r := range results {
    		fmt.Println("results :", r)
    	}
    }
    
    

    go run workerpool.go 报错

    start job 1
    finish job 1
    start job 2
    results : 1
    finish job 2
    start job 3
    results : 2
    finish job 3
    start job 4
    results : 3
    finish job 4
    start job 5
    results : 4
    finish job 5
    fatal error: all goroutines are asleep - deadlock!
    results : 5
    
    goroutine 1 [chan receive]:
    main.main()
    	workerpool.go:30 +0x19d
    

    asleep就是说协程都在睡觉没做事
    问题应该出在遍历jobs上, jobs遍历完没数据可操作了,引发 asleep - deadlock 报错
    改进方法:
    1、是无限循环输入数据到jobs
    2、用waitGroup

    方法1的无限循环输入数据就不做介绍了,比较简单
    下面展示一下方法2使用waitGroup的方式

    
    package main
    
    import (
    	"fmt"
    	"sync"
    	"time"
    )
    
    var wg sync.WaitGroup
    
    //工作线程
    func workerPool(jobs <-chan int, results chan<- int) {
    	for j := range jobs {
    		fmt.Println("start job", j)
    		time.Sleep(time.Second)
    		fmt.Println("finish job", j)
    		results <- j
    	}
    }
    
    func init() {
    	wg = sync.WaitGroup{}
    }
    
    func main() {
    	const numJobs = 5
    	jobs := make(chan int)    //
    	results := make(chan int) //
    
    	go workerPool(jobs, results)
    	go func() {
    		for r := range results {
    			fmt.Println("results :", r)
    			wg.Done()//接收到数据,表示完成了一份工作
    		}
    	}()
    
    	for i := 1; i <= numJobs; i++ {
    		wg.Add(1)//标记开始一份工作
    		jobs <- i
    	}
    
    	wg.Wait()
    
    }
    
    

    正常运行结果如下:
    start job 1
    finish job 1
    start job 2
    results : 1
    finish job 2
    start job 3
    results : 2
    finish job 3
    start job 4
    results : 3
    finish job 4
    start job 5
    results : 4
    finish job 5
    results : 5

    Process finished with exit code 0

  • 相关阅读:
    使用参数化SQL语句进行模糊查找(转载)
    ASP.NET 数据绑定控件(转)
    C#把datetime类型的日期转化成其他格式方法总结
    asp.net MVC中form提交和控制器接受form提交过来的数据(转)
    图说世界编程语言排行
    Android笔记——Matrix
    设计模式——代理模式
    Android笔记——Handler Runnable与Thread的区别
    Android笔记——AsyncTask介绍
    Eclipse---java项目导入报错更改
  • 原文地址:https://www.cnblogs.com/imbin/p/15013484.html
Copyright © 2011-2022 走看看