現代のソフトウェア開発において、並列処理は重要な概念です。Go言語は言語レベルで並列処理をサポートし、マルチコアCPUの能力を最大限に活用できるよう設計されています。
goroutineの仕組み
Javaではスレッドを直接生成しますが、Goでは「go」キーワードを使用して軽量なgoroutineを生成します。goroutineは非常に軽量で、数百万単位で作成可能です。
// 関数をgoroutineで実行
go processTask()
// 無名関数をgoroutineで実行
go func() {
// 処理内容
}()
GPMスケジューリングモデル
Goの並列処理は以下のコンポーネントで構成されます:
- G (Goroutine): 実行単位
- P (Processor): 実行リソースを管理
- M (Machine): OSスレッドを抽象化
スケジューラはグローバルキューとローカルキューを使用してgoroutineを効率的に分配します。各Pは最大256個のGを保持でき、超過時はグローバルキューに移動されます。
チャネルの活用
並列処理ではデータ交換が重要です。Goでは共有メモリではなく、チャネルを使用して安全にデータをやり取りします。
// チャネルの作成
msgChannel := make(chan string)
// データ送信
go func() { msgChannel <- "data" }()
// データ受信
message := <-msgChannel
ミューテックスの特徴
Goのsync.Mutexは以下の特徴を持ちます:
- 軽量な実装
- 自旋ロックによる効率化
- 最適化された待機キュー
- コンテキストスイッチの削減
var mutex sync.Mutex
var counter int
func increment() {
mutex.Lock()
counter++
mutex.Unlock()
}
並列処理のパフォーマンス比較
Goの並列処理モデルは以下の点で優れています:
- リソース消費が少ない
- コンテキストスイッチが最小限
- デッドロックリスクが低減
- スケーラビリティが高い