Go言語の並行処理で発生するトラブル事例と解決法まとめ
生徒
「Goで複数のgoroutineを動かすと、どんなトラブルが起きるんですか?」
先生
「代表的なのは、競合状態やデッドロックです。競合状態は複数のgoroutineが同じ変数を同時に操作するときに起こります。デッドロックは、goroutineが互いに待ち状態になり処理が止まってしまうことです。」
生徒
「それを防ぐにはどうすればいいですか?」
先生
「channelやsyncを適切に使うこと、そして-raceオプションを使ったデバッグが有効です。順番に具体例を見ていきましょう。」
1. 競合状態(Race Condition)と解決法
競合状態は、複数のgoroutineが同じメモリを同時に書き換えるときに発生します。これにより意図しない結果が生じることがあります。Goではsync.Mutexやchannelを使って解決できます。
2. 競合状態のサンプルと-raceオプション
package main
import (
"fmt"
"sync"
)
func main() {
counter := 0
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
counter++ // 競合状態発生
wg.Done()
}()
}
wg.Wait()
fmt.Println("Counter:", counter)
}
このコードをgo run -race main.goで実行すると、競合状態が検出されます。Mutexを使うことで安全に更新可能です。
3. Mutexで競合状態を防ぐ方法
var mu sync.Mutex
go func() {
mu.Lock()
counter++
mu.Unlock()
wg.Done()
}()
Mutexでロックとアンロックを行うことで、同時アクセスによるデータ破損を防ぎます。
4. デッドロックとその解決法
デッドロックは、複数のgoroutineが互いに相手の処理完了を待ち続けてしまう状態です。特にchannelを使った送受信で発生しやすく、送信側と受信側が揃わない場合に起こります。
5. デッドロックの例と回避
ch := make(chan int)
go func() {
ch <- 1 // 受信側がないとデッドロック
}()
// main goroutineで受信
fmt.Println(<-ch)
受信がないまま送信すると、処理が止まります。必ず送信と受信が揃うようにgoroutineを設計することが重要です。
6. channelの閉鎖忘れによる問題
channelは使い終わったらclose()で閉じるのが安全です。閉じないと、受信側が永遠に待ってしまうことがあります。
ch := make(chan int)
go func() {
ch <- 100
close(ch) // 忘れずに閉じる
}()
for v := range ch {
fmt.Println(v)
}
7. ゴルーチンリークの防止
goroutineリークとは、終了すべきgoroutineがいつまでも動き続けることです。contextパッケージを使ってタイムアウトやキャンセルを設定することで防げます。
ctx, cancel := context.WithCancel(context.Background())
go func() {
select {
case <-ctx.Done():
return
}
}()
cancel() // goroutineを終了
8. トラブルを防ぐ設計のポイント
- 共有変数への同時アクセスにはsync.Mutexやsync.RWMutexを使う
- データの受け渡しはchannelを使い、送受信の順序を揃える
- goroutineの終了待ちはsync.WaitGroupで管理する
- goroutineリーク防止のためにcontextでキャンセルやタイムアウトを設定する
- 競合状態のチェックには
-raceオプションを活用する
これらを組み合わせることで、Goの並行処理で発生するトラブルを未然に防ぎ、安全なプログラム設計が可能です。
【超入門】ゼロから始めるGo言語プログラミング:最速で「動くアプリ」を作るマンツーマン指導
「プログラミングの仕組み」が根本からわかる。Go言語でバックエンド開発の第一歩を。
本講座を受講することで、単なる文法の暗記ではなく、「プログラムがコンピュータの中でどう動いているか」という本質的な理解につながります。シンプルながら強力なGo言語(Golang)を通じて、現代のバックエンドエンジニアに求められる基礎体力を最短距離で身につけます。
具体的な開発内容と環境
【つくるもの】
ターミナル(黒い画面)上で動作する「対話型計算プログラム」や、データを整理して表示する「ミニ・ツール」をゼロから作成します。自分の書いたコードが形になる感動を体験してください。
【開発環境】
プロの現場でシェアNo.1のVisual Studio Code (VS Code)を使用します。インストールから日本語化、Go言語用の拡張機能設定まで、現場基準の環境を一緒に構築します。
この60分で得られる3つの理解
「なぜ動くのか」という設定の仕組みを理解し、今後の独学で詰まらない土台を作ります。
データの種類やメモリの概念など、他言語にも通じるプログラミングの本質を学びます。
ただ動くだけでなく、誰が見ても分かりやすい「綺麗なコード」を書くための考え方を伝授します。
※本講座は、将来的にバックエンドエンジニアやクラウドインフラに興味がある未経験者のためのエントリー講座です。マンツーマン形式により、あなたの理解度に合わせて進行します。
初めてのGo言語を一緒に学びましょう!