std::atomicとメモリーオーダー
正確性と速度に適したメモリーオーダーでstd::atomicを使います。
「std::atomicとメモリーオーダー」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン1/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
ミューテックスの先へ
ロックはアクセスを直列化します。単純で正しい一方、スループットを制限します。std::atomic は、高スループットの並行コード向けに、ロックを使わない構成要素を提供します。
std::atomic の基本
std::atomic<T> は値をラップし、アトミックな read-modify-write 操作をサポートします。
#include <atomic>
std::atomic<int> counter{0};
counter.fetch_add(1); // atomic increment
int v = counter.load();
counter.store(0);便利な演算子
算術型では、通常の演算子もアトミックに動作します。
std::atomic<int> n{0};
++n; // atomic increment
n += 5; // atomic add
int v = n; // atomic loadアトミック操作が難しい理由
CPU はコア間でメモリ操作の順序を入れ替えることがあります。メモリ順序によって、どの並べ替えが許可されるかを指定します。
メモリ順序
よく使われる5つの順序は次のとおりです。
memory_order_relaxed— アトミックですが順序付けは行わないmemory_order_acquire— release と組み合わせる。後続の並べ替えを許可しないmemory_order_release— acquire と組み合わせる。先行する並べ替えを許可しないmemory_order_acq_rel— 両方memory_order_seq_cst— 順序一貫性を保証する(デフォルト)
逐次一貫性:安全なデフォルト
デフォルトの seq_cst は直感的に動作し、すべてのアトミック操作が単一のグローバルな順序で実行されるように見えます。relaxed 系の順序より遅くなりますが、動作を理解しやすくなります。
Acquire-Release の組み合わせ
プロデューサーでは release を、コンシューマーでは acquire を使用します。acquire の後では、対応する release より前に行われたすべての書き込みが見えるようになります。
std::atomic<bool> ready{false};
int data = 0;
// producer
data = 42;
ready.store(true, std::memory_order_release);
// consumer
while (!ready.load(std::memory_order_acquire));
std::cout << data; // sees 42Relaxed 順序
relaxed のアトミック操作はアトミック性(読み取りが途中で分割されないこと)を保証しますが、任意の並べ替えを許可します。順序が重要でない単純なカウンターに使用してください。
Compare-and-Swap
ほとんどのロックフリーアルゴリズムの基盤です。compare_exchange_strong(expected, desired) は、現在の値が expected と等しい場合にのみ、アトミックに更新します。
std::atomic<int> a{10};
int expected = 10;
bool ok = a.compare_exchange_strong(expected, 20);
// if true, a is now 20; otherwise expected holds the actual current valueWeak と Strong の CAS
compare_exchange_weak は、値が一致していても誤って失敗することがあります。一部のプラットフォームでは strong より低コストなため、ループ内で使用してください。ループの外では strong を使用します。
ロックフリーとウェイトフリー
進行保証には次の2種類があります。
- ロックフリー — 常に少なくとも1つのスレッドが進行する
- ウェイトフリー — すべてのスレッドが有限時間内に進行する
アトミック操作を使う場面
アトミック操作がミューテックスより常に高速とは限りません。カウンター、フラグ、単純な状態など、クリティカルパスを単純に保てる場合に使用してください。複雑な共有状態には、通常、ミューテックスのほうが安全でわかりやすくなります。
確認問題
最も強い保証を持つ一方で、最も遅いメモリ順序はどれですか。
まとめ
std::atomic は、明示的なメモリ順序付けを備えたロックフリーのプリミティブを提供します。デフォルトでは memory_order_seq_cst を使用し、プロデューサーとコンシューマーのパターンには acquire/release の組み合わせを使用してください。relaxed は、カウンターのような順序付けを必要としないアトミック操作にのみ使用します。
よくある質問
「std::atomicとメモリーオーダー」レッスンは無料ですか?
はい。「std::atomicとメモリーオーダー」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「std::atomicとメモリーオーダー」で何を学びますか?
正確性と速度に適したメモリーオーダーでstd::atomicを使います。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン1/4です。
「std::atomicとメモリーオーダー」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- std::atomicとメモリーオーダー
- 比較交換(CAS)パターン
- ロックフリーキューの実装
- ハザードポインターとABA問題