Go言語におけるatomic.AddInt64の内部実装解析

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

このコードは以下の処理を行います:

  1. 競合検出用の関数をAXレジスタにロード
  2. 原子操作を実行
  3. 加算結果を計算

原子操作の種類

並行プログラミングでは、主に2種類の原子加算操作が存在します:

  • fetch_add: 現在の値を読み取ってから加算を行い、加算前の値を返す
  • add_fetch: 加算を行ってから新しい値を返す

実際の使用例

var counter int64
atomic.AddInt64(&counter, 1)  // カウンタをアトミックにインクリメント

この操作はマルチスレッド環境でも安全に使用できますが、32ビットプラットフォームでは注意が必要です。

タグ: Go atomic AddInt64 並行処理 アセンブリ

6月7日 21:16 投稿