0
0

More than 3 years have passed since last update.

【Go/golang】sync.Mutex / sync.WaitGroupで排他制御をする

Last updated at Posted at 2021-03-14

※本記事は備忘録として記述しておりますので、ご容赦ください。

sync.Mutex

次のコードは、IDを作成するコードが同時に1つしか実行されないようにしています。
※goroutineにmutex構造体を渡すときは、必ずポインタでわたすこと。
値のまま渡してしまうと、ロックしている状態のまま別のsync.Mutexインスタンスを渡すことになってしまうので、注意が必要です。

package main

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

var id int

func generateID(mutex *sync.Mutex) int {
    // Lock() / Unlock()をペアで呼び出してロックする
    mutex.Lock()
    defer mutex.Unlock()

    id++
    result := id

    return result
}

func main(){
    // sync.Mutex構造体の変数宣言
    // 次の宣言をしてもポインタ型になるだけで正常に動作する
    // mutex := new(sync.Mutex)
    var mutex sync.Mutex

    for i := 0; i < 100; i++ {
        go func() {
            fmt.Printf("id: %d\n", generateID(&mutex))
        }()
    }
    // 100まで出力させたいなら終了待ちの操作が必要
    // time.Sleep(4 * time.Second)
}
# 実行結果
id: 1
id: 5
id: 6
id: 2
id: 7
id: 4
id: 3
id: 8
id: 10
id: 11
id: 12
id: 13
id: 14
id: 15
id: 16
id: 17
id: 18
id: 9
id: 19
id: 20
...
省略

# goroutineの終了待ちをしていないので、100個に到達する前に終了してしまうことがある

ロックしたままの値を渡していないか確認するには、go vetを実行することで見ることができる。

Mutexとチャネルの使い分け

  • チャネルが有用な場合
    • 非同期で結果を受け取る場合
  • Mutexが有用な場合
    • キャッシュ、状態管理

sync.WaitGroup

多数のgoroutineで実行しているジョブの終了待ちに使います。
※goroutineにwg構造体を渡すときは、Mutex同様必ずポインタでわたすこと。

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup

    // ジョブ数をあらかじめ登録 (必ずgoroutineを作成する前に呼ぶ)
    // Doneが呼ばれるたびに、数がデクリメントされていく
    // Waitはこの中の数が0になるのを待機している
    wg.Add(2)

    go func() {
        // 非同期で仕事をする
        fmt.Println("仕事1")
        // Doneで完了を通知
        wg.Done()
    }()

    go func() {
        // 非同期で仕事をする
        fmt.Println("仕事2")
        // Doneで完了を通知
        wg.Done()
    }()

    // 全ての処理が終わるのを待つ
    wg.Wait()
    fmt.Println("完了")
}
# 出力結果 (仕事1と仕事2は順不同で出力される)
仕事2
仕事1
完了

# Mutexと違い、終了待ちをしているため、確実にgoroutineの終了を確認できる

WaitGroupとチャネルの使い分け

  • WaitGroupの方が良い場合
    • ジョブ数が大量にある場合
    • 可変個の場合
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0