atomic.AddInt64の動作原理
Go言語のatomic.AddInt64関数は、アトミックな加算操作を提供します。この関数は以下の特徴を持っています:
// AddInt64はdeltaを*addrにアトミックに加算し、新しい値を返します
// 32ビットプラットフォームではバグが存在する可能性があるため注意が必要です
func AddInt64(addr *int64, delta int64) (new int64)
実装の詳細
実際の実装はアセンブリレベルで行われており、以下のようなリンク名が使用されます:
//go:linkname abigen_sync_atomic_AddInt64 sync/atomic.AddInt64
func abigen_sync_atomic_AddInt64(addr *int64, delta int64) (new int64)
アセンブリコードの構造
TEXT sync∕atomic·AddInt64(SB), NOSPLIT|NOFRAME, $0-24
GO_ARGS
MOVQ $__tsan_go_atomic64_fetch_add(SB), AX
CALL racecallatomic<>(SB)
MOVQ add+8(FP), AX
ADDQ AX, ret+16(FP)
RET
このコードは以下の処理を行います:
- 競合検出用の関数をAXレジスタにロード
- 原子操作を実行
- 加算結果を計算
原子操作の種類
並行プログラミングでは、主に2種類の原子加算操作が存在します:
- fetch_add: 現在の値を読み取ってから加算を行い、加算前の値を返す
- add_fetch: 加算を行ってから新しい値を返す
実際の使用例
var counter int64
atomic.AddInt64(&counter, 1) // カウンタをアトミックにインクリメント
この操作はマルチスレッド環境でも安全に使用できますが、32ビットプラットフォームでは注意が必要です。