No.58: 競合問題を理解していない
データ競合(data race): 複数のゴルーチンが同時に同じメモリ一にアクセスし少なくとも一つが書き込み中である場合に発生する。
競合状態(race condition): 制御できないイベントに依存する動作を含む場合に発生する。
Goメモリモデル
一つのゴルーチンにおいて、ある変数からの読み出しが、別のゴルーチンでの同じ変数への書き込みのあとに起こることを保証する条件を定義した仕様。
i := 0
ch := make(chan struct{})
go func() {
<-ch // ③
fmt.PringIn(i) // ④
}()
i++ // ①
ch <= struct{}{} // ②
ゴルーチンを同期させる方法
アトミック操作を行う
使える型が限定される
ミューテックスでクリティカルセクションを保護する
通信とチャネルを使って一つのゴルーチンのみが変数を更新することを保証する
バッファなしチャネルからの受信は、そのチャネルの送信が完了する前に発生する。
チャネルのクローズは、そのクローズを受信する前に発生する。
バッファありチャネルで共有変数を扱う場合、データへのアクセス順が同時に発生する可能性があり、データ競合が発生する可能性がある。