/*
お題: subPerson1が終了したら subPerson2も巻き添えで強制的に終了させるには?
当初、一方が終了したら、他方も終了するように作りたかったのだけど、分からなかったので、subPerson1 → subPerson2 の順番で終わせるような実装にした
*/
package main
import (
"fmt"
"sync"
"time"
)
func subPerson1(i int, wg *sync.WaitGroup, ch chan struct{}) {
defer wg.Done()
time.Sleep(1 * time.Second)
fmt.Println(" End of sub_person1(", i, ")")
close(ch) // subPerson2に終了を通知する
}
func subPerson2(i int, wg *sync.WaitGroup, ch chan struct{}) {
defer wg.Done()
<-ch // subPerson1 のclose(ch)が発行されるまでロック (普通はselect待ちにする)
fmt.Println(" End of sub_person2(", i, ")")
}
func person(i int, wg *sync.WaitGroup) {
fmt.Println(" Start... person(", i, ")")
defer wg.Done()
subWG := sync.WaitGroup{}
subWG.Add(2)
ch := make(chan struct{})
go subPerson1(i, &subWG, ch)
go subPerson2(i, &subWG, ch)
subWG.Wait()
fmt.Println(" End... person(", i, ")")
}
func main() {
fmt.Println("start... main()")
wg := sync.WaitGroup{}
for i := 0; i < 5; i++ {
wg.Add(1) // goルーチンを実行する関数分だけAddする
go person(i, &wg)
}
wg.Wait()
fmt.Println("end of ... main()")
}
ebata@DESKTOP-P6KREM0 MINGW64 ~/goga/0-2
$ go run main.go
start... main()
Start... person( 4 )
Start... person( 0 )
Start... person( 1 )
Start... person( 3 )
Start... person( 2 )
End of sub_person1( 3 )
End of sub_person2( 3 )
End... person( 3 )
End of sub_person1( 0 )
End of sub_person1( 4 )
End of sub_person2( 4 )
End... person( 4 )
End of sub_person2( 0 )
End... person( 0 )
End of sub_person1( 1 )
End of sub_person2( 1 )
End... person( 1 )
End of sub_person1( 2 )
End of sub_person2( 2 )
End... person( 2 )
end of ... main()
とまあこんな感じで、sub_person1 → sub_person2 → person という順番でgoroutineが終了していることが確認できました。