C++ Academy · レッスン

比較交換(CAS)パターン

compare_exchange_weakとcompare_exchange_strongで、ロックフリーな更新を実装します。

レッスン 2/414 ステップ

「比較交換(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フィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. std::atomicとメモリーオーダー
  2. 比較交換(CAS)パターン
  3. ロックフリーキューの実装
  4. ハザードポインターとABA問題
← C++ Academyに戻る