goroutineに対して一斉にシグナルを送る

たまに待ち受けてる複数のgoroutineに対して一斉にシグナルを送りたいことがあると思います。

そういう時はsync.Condを使うと楽にできるみたいです。

こんな感じです。

package main

import (
    "fmt"
    "sync"
    "time"
)

func main() {
    fmt.Println("シグナルを送ってください")

    l := sync.Mutex{}
    c := sync.NewCond(&l)
    for i := 0; i < 10; i++ {
        go func(j int) {
            l.Lock()
            defer l.Unlock()
            c.Wait()
            fmt.Printf("生徒%d「はいっ!」\n", j)
        }(i)
    }

    var stdin string
    fmt.Scan(&stdin)
    if stdin == "返事は?" {
        c.Broadcast()
    }
    time.Sleep(3 * time.Second)
}

これを実行すると10個のgoroutineが起動し、標準入力を待ち受ける状態になります。

そこで「返事は?」と入力すると、sync.CondのBroadcastが実行され、一斉にgoroutineが動き出します。

出力としてはこんな感じです。

$ go run main.go
シグナルを送ってください
返事は?
生徒1「はいっ!」
生徒9「はいっ!」
生徒7「はいっ!」
生徒6「はいっ!」
生徒4「はいっ!」
生徒5「はいっ!」
生徒3「はいっ!」
生徒8「はいっ!」
生徒2「はいっ!」
生徒0「はいっ!」

構造化と性能の間をGolangで攻める技術を読んでいて、syncパッケージについて触れている章があって、それ見てこういうこともできるなーと思いついた感じでした。

以上、小ネタでした。