semaphore(同時実行数制限)【Go】
goroutineの同時実行数を制限することができるpackageです。
golang.orgから提供されていますが、goのmainツリーとは別のプロジェクトになります。
そのため、使用するには、下記コマンドを実行してインストールする必要があります。
$ go get golang.org/x/sync/semaphore
下記例は、goroutineの同時実行を最大2つまでに制限します。
また、contextの生成が必須になります。
var sn = semaphore.NewWeighted(2) // goroutineの同時実行を最大2つまでに制限 func longProcess(ctx context.Context) { if err := sn.Acquire(ctx, 1); err != nil { // 指定した同時実行数制限snから1つ実行権限を取得。上限に達していて取得できない場合は、取得でき次第、実行を開始 log.Fatalln(err) } defer sn.Release(1) // 最後にsn実行権限枠を1つ空ける fmt.Println("start..") time.Sleep(1 * time.Second) fmt.Println("done") } func main() { ctx := context.TODO() // contextの機能は今回利用しないため、TODOとする go longProcess(ctx) go longProcess(ctx) go longProcess(ctx) time.Sleep(4 * time.Second) // main関数が事前に終了してしまわないようsleep }
上記例では、同時実行できないものについて、
semaphore.NewWeighted(i int).Acquire(ctx context, j int) error を用いて、
実行権限の枠が取得でき次第、実行を開始させました。
下記例では、同時実行できないものについては、処理を実行させないようにすることができます。
var sn = semaphore.NewWeighted(2) func longProcess() { if !sn.TryAcquire(1) { // 実行権限が取得できるかどうか、bool値を返す fmt.Println("could not acquire") return // 上限に達していて、実行権限が取得できない場合は処理を終了させる } defer sn.Release(1) fmt.Println("start..") time.Sleep(1 * time.Second) fmt.Println("done") } func main() { go longProcess() go longProcess() go longProcess() time.Sleep(3 * time.Second) go longProcess() time.Sleep(2 * time.Second) }
semaphore.NewWeighted(i int).TryAcquire(j int) boolの実行に際しては、
context.Contextは必要ありません。