std::atomic: ロックフリー同期
mutex より軽量。カウンタやフラグに最適。
std::atomic
ロックフリーのスレッドセーフ型。
CAS
Compare-And-Swap。条件付き交換。
ロックフリー
mutex なしで同期。
atomic 基礎
通常の `count++` は「読み込み→加算→書き込み」の3ステップで行われるため、途中で他スレッドが割り込むとデータが壊れます。`std::atomic` はこれを CPU の命令レベルで1つの操作として行うため、ロックなし(Lock-Free)で安全に共有できます。
#include <atomic>
std::atomic<int> counter{0};
// スレッドセーフなインクリメントvoid increment() { counter++; // アトミック操作 counter.fetch_add(1); // 明示的に}
// 読み書きint val = counter.load();counter.store(100);
// 比較交換(CAS)int expected = 0;bool success = counter.compare_exchange_strong(expected, 1);実行結果
counter++ → アトミックに+1\nload() / store() で安全に読み書き
Bad
// ❌ Bad: mutex でカウンタ保護std::mutex m;int counter = 0;{ std::lock_guard lock(m); counter++; // 重い}Good
// ✅ Good: atomicstd::atomic<int> counter{0};counter++; // ロックフリーパターン
// フラグstd::atomic<bool> done{false};// スレッド1done.store(true);// スレッド2while (!done.load()) { }
// メモリオーダー(上級)counter.store(42, std::memory_order_release);int val = counter.load(std::memory_order_acquire);
// atomic_flag(最も軽量)std::atomic_flag flag = ATOMIC_FLAG_INIT;while (flag.test_and_set()) { } // スピンロック// クリティカルセクションflag.clear();
// C++20: wait/notifystd::atomic<int> signal{0};signal.wait(0); // 0以外になるまで待機signal.store(1);signal.notify_one(); // 待機を解除 Tip: シンプルなカウンタやフラグには atomic。複雑な操作には mutex。
合格ライン
load/store を使える
atomic と mutex を使い分けられる
参考リンク
演習課題
課題1: atomic カウンタ
std::atomic<int> で複数スレッドから安全にカウンタをインクリメントしてください。
課題2: CAS
compare_exchange_weak を使って条件付き更新を実装してください。