package main
import (
"fmt"
"runtime"
"sync"
"time"
)
func main() {
intInputChan := make(chan int, 50)
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go worker(intInputChan, wg)
}
for i := 1; i < 51; i++ {
fmt.Printf("Inputs. %d \n", i)
intInputChan <- i
}
close(intInputChan)
wg.Wait()
fmt.Println("Existing Main App... ")
panic("---------------")
}
func worker(input chan int, wg sync.WaitGroup) {
defer func() {
fmt.Println("Executing defer..")
wg.Done()
}()
for {
select {
case intVal, ok := <-input:
time.Sleep(100 * time.Millisecond)
if !ok {
input = nil
return
}
fmt.Printf("%d %v\n", intVal, ok)
default:
runtime.Gosched()
}
}
}
抛出的错误是。
致命错误:所有goroutine都睡着了 - 死锁!
goroutine 1 [semacquire]: 同步。(* WaitGroup).Wait(0xc082004600) c:/go/src/sync/waitgroup.go:132 + 0x170 main.main() E:/Go/go_projects/go/src/Test.go:22 + 0x21a
答案 0 :(得分:8)
我刚试过它(playground)传递wg *sync.WaitGroup
并且它有效。
传递sync.WaitGroup
表示传递sync.WaitGroup
的副本(通过值传递):goroutine提到Done()
到不同的 sync.WaitGroup
。
var wg sync.WaitGroup
for i := 0; i < 3; i++ {
wg.Add(1)
go worker(intInputChan, &wg)
}
注意&wg
:您正在通过值传递指向原始sync.WaitGroup
的指针,以供goroutine使用。
答案 1 :(得分:3)
如上所述,请不要在sync
package documentation的顶部附近按值传递同步包中的类型:“不应复制包含此程序包中定义的类型的值。“这也包括类型本身(sync.Mutex
,sync.WaitGroup
等。”
然而,有几点说明:
wg.Add
一次调用(但是如果有文档记录,请确保 之前可以调用{{1} })。Wait
;它使工人忙碌。runtime.Gosched
从频道中读取,以便在关闭时简化停止。将其转化为:
range