比較交換(CAS)パターン
compare_exchange_weakとcompare_exchange_strongで、ロックフリーな更新を実装します。
「比較交換(CAS)パターン」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。
CAS プリミティブ
Compare-and-swap は、アトミックに読み取り、比較し、条件付きで書き込みます。ほとんどのロックフリーアルゴリズムの基盤です。
C++ の Compare Exchange
std::atomic には次の2つのバリエーションがあります。
compare_exchange_strong(expected, desired)— 現在の値が expected と等しい場合に成功するcompare_exchange_weak(expected, desired)— 誤って失敗することがある
CAS ループの構造
典型的な CAS ループでは、読み取り、計算、書き込みの試行を行います。別のスレッドが競争に勝った場合は再試行します。
std::atomic<int> a{0};
int old = a.load();
int next;
do {
next = compute_new(old);
} while (!a.compare_exchange_weak(old, next));アトミック更新への CAS の使用
新しい値が古い値に依存する場合は CAS を使用します。通常の store では、同時実行するスレッドによる更新が失われます。
// Atomic max
int current = a.load();
while (newval > current && !a.compare_exchange_weak(current, newval));ロックフリースタック:Push
単純なロックフリースタックへの push では、CAS を使用して新しいノードを先頭に追加します。
struct Node { int value; Node* next; };
std::atomic<Node*> head{nullptr};
void push(int v) {
Node* n = new Node{v, nullptr};
n->next = head.load();
while (!head.compare_exchange_weak(n->next, n));
}誤った失敗
compare_exchange_weak は、値が一致していても失敗することがあります。これは、基盤の命令が失敗を許可している ARM などのプラットフォームで発生します。ループ内で使用し、再試行のコストが高い場合は strong を使用してください。
更新パターン:リセット
値が変更されていない場合にのみ、既知の状態へリセットします。
int expected = 42;
if (a.compare_exchange_strong(expected, 0)) {
// a was 42 and is now 0
}構成要素:アトミックカウンター
単純なカウンターには、CAS ループより fetch_add のほうが簡潔で高速です。
構成要素:アトミックフラグ
単純なブール値のフラグには、std::atomic_flag が std::atomic<bool> より軽量で、test_and_set をサポートします。
並行性について考える
ロックフリーコードは、動作を理解するのが非常に難しいことで知られています。厳密なテスト(TSan、ファジング)や、利用できる場合は形式モデルを使用し、実績のある既存の実装を優先してください。
CAS を選ぶ場面
次の場合に CAS を使用してください。
- 複数のスレッドが同じ値を頻繁に更新する
- ミューテックスの競合がボトルネックになっている
- クリティカルセクションが非常に短く単純である
CAS を使わない場面
次の場合は CAS を避けてください。
- 更新に数個を超える操作が必要である
- スループットより正しさが重要である
- チームにロックフリープログラミングの知識が不足している
確認問題
通常、compare_exchange_weak をループ内で使用するのはなぜですか。
まとめ
Compare-and-swap は、値が期待値と等しい場合にのみ、値をアトミックに更新します。CAS ループを使うと、ロックなしで同時実行される更新を処理できます。ループ内では compare_exchange_weak を使用し、1回だけ試行する場合は strong を使用してください。
AI チューターと学ぶ C++ — 無料
ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。
- コース
- 51
- レッスン
- 203
よくある質問
「比較交換(CAS)パターン」レッスンは無料ですか?
はい。「比較交換(CAS)パターン」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。
「比較交換(CAS)パターン」で何を学びますか?
compare_exchange_weakとcompare_exchange_strongで、ロックフリーな更新を実装します。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
C++ Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。
「比較交換(CAS)パターン」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このC++ Academyレッスンでコードを書いて実行できますか?
はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- std::atomicとメモリーオーダー
- 比較交換(CAS)パターン
- ロックフリーキューの実装
- ハザードポインターとABA問題