概要
Go言語では、複数のゴルーチン(スレッド)が同時に実行されることがあるため、共有リソースへのアクセス制御が必要です。そのために、mutex(ミューテックス)と呼ばれる排他制御機構が提供されています。mutexを使うことで、複数のゴルーチンから同時にアクセスされた場合に、競合状態(race condition)を避けることができます。
サンプルコード
以下のサンプルコードでは、3つのゴルーチンがそれぞれカウントアップを行います。しかし、共有変数であるcountに複数のゴルーチンから同時にアクセスされるため、競合状態が発生します。そこで、mutexを使ってcountに対するアクセスを排他制御します。
package main
import (
"fmt"
"sync"
)
func main() {
var count int
var wg sync.WaitGroup
var mu sync.Mutex
for i := 0; i < 3; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for j := 0; j < 100000; j++ {
mu.Lock()
count++
mu.Unlock()
}
}()
}
wg.Wait()
fmt.Println("count:", count)
}
解説
- sync.Mutexを使ってmutexを生成します。
- ゴルーチンが共有する変数countを定義します。初期値は0です。
- sync.WaitGroupを使って、3つのゴルーチンが終了するまで待機するようにします。
- 3つのゴルーチンを生成します。wg.Add(1)でWaitGroupにゴルーチンを追加し、defer wg.Done()でゴルーチンが終了したことをWaitGroupに通知します。
- ゴルーチンの中で、forループを使って100000回カウントアップを行います。mu.Lock()でmutexをロックし、countをインクリメントして、mu.Unlock()でmutexをアンロックします。
- wg.Wait()で、3つのゴルーチンがすべて終了するまで待機します。
- 最後に、countの値を表示します。
このように、mutexを使うことで、countに対するアクセスを排他制御し、競合状態を避けることができます。