emahiro/b.log

日々の勉強の記録とか育児の記録とか。

semaphore を使って goroutine の起動数を Go から排他制御する

Overview

sync package 内にある semaphore を使って Go のアプリケーション側で goroutine の起動数を排他制御します。

Go の並行処理の起動数を制御するのは

使い方

https://pkg.go.dev/golang.org/x/sync/semaphore#section-documentation のサンプルにある実装方法に準拠するだけでOKです。

// goroutine の上限を指定する。
var maxConcurrentNum int64 = 20
sem := semaphore.NewWeighted(maxConcurrentNum)

ctx := context.Backgrdound()

for i := range 20 {
    if err := sem.Acquire(ctx, 1); err != nil {
        return err
    }

    go func(ctx context.Context) {
        defer func() {
            sem.Release(1)
            if err := recover(); err != nil {
                fmt.Errorf("err: %v\n", err)
            }
        }()
        // do concurrent proccess without cancel context
        cctx := context.WithoutCancel(ctx)
    }(ctx)
}


// 最期に全部の worker pool を取得して、意図しないプロセスがゾンビとして残らないようにする。
if err := sem.Acquire(ctx, maxConcurrentNum); err != nil {
    return err
}

注意点として semaphore を Acquire する(P操作)ときに、 TryAcquire というメソッドも利用できますが、これは「利用可能か」の結果を返すだけのメソッドなので、Godoc の使い方の通り Acquire メソッドを使いましょう。こちらは semaphore に利用可能なプロセスがあるか、が充填されるまで処理を Blocking してくれます。

See Also

wa3.i-3-i.info

soarflat777.hatenablog.com