今天进行一个协程操作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