0Pricing
C++ Academy · レッスン

std::mutex、lock_guard、unique_lock

mutexとRAIIによるロックヘルパーで共有状態を保護します。

「std::mutex、lock_guard、unique_lock」はCoddyKit上の無料C++ Academyレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはC++ Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 C++ Academyコースには全4レッスンが含まれています。

なぜミューテックスが必要なのか

複数のスレッドが同じデータにアクセスすると、データを奪い合う競合が発生します。ミューテックスは相互排他を保証し、一度に1つのスレッドだけがロックを保持できるようにします。

std::mutexの基本

構築し、ロックし、アンロックします。手動ロックはエラーが起こりやすいため、必ずRAIIヘルパーを使用してください。

#include <mutex>
std::mutex mtx;

mtx.lock();
// critical section
mtx.unlock();

std::lock_guard:RAIIロック

最もシンプルなRAIIロックです。コンストラクターでロックし、デストラクターでアンロックします。例外を送出しないクリティカルセクションに最適です。

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx);
    ++counter;
}

std::scoped_lock(C++17)

lock_guardに似ていますが、複数のミューテックスをデッドロックなしで一度にロックできます。現代的なコードではこちらを優先してください。

#include <mutex>
std::scoped_lock lock(mtx1, mtx2, mtx3);  // locks all atomically

std::unique_lock:柔軟なロック

lock_guardより多くの機能を備えています:

  • スコープの途中でアンロックと再ロックができます
  • ムーブできます(所有権を移譲できます)
  • 条件変数と組み合わせて使用します
std::unique_lock<std::mutex> lock(mtx);
lock.unlock();        // release temporarily
// ... do something without the lock ...
lock.lock();           // reacquire

デッドロックの回避

2つのスレッドが異なる順序でロックを取得すると、デッドロックが発生する可能性があります。常に一貫した全体順序で取得するか、複数のミューテックスに対してstd::scoped_lockを使用してください。

複数のミューテックスに対するstd::lock

C++17より前では、複数のミューテックスをアトミックに取得するためにstd::lockを使用します。C++17のstd::scoped_lockのほうが簡潔です。

再帰ミューテックス

std::recursive_mutexを使うと、1つのスレッドが同じミューテックスを複数回ロックできます。通常は設計上の問題の兆候なので、代わりにリファクタリングしてください。

try_lockとtimed_mutex

ロックが保持されている場合、try_lockは直ちに戻ります。std::timed_mutexは、時間制限付きのロック試行をサポートします。

リーダー・ライターロック

std::shared_mutex(C++17)を使うと、複数の読み取り側が同時にアクセスするか、1つの書き込み側が排他的にアクセスできます。読み取りが多い処理に使用します。

std::shared_mutex sm;
void read()  { std::shared_lock lk(sm);   /* read */ }
void write() { std::unique_lock lk(sm);   /* write */ }

粒度のトレードオフ

ロックの粒度が粗すぎると並行性が損なわれます。細かすぎるとオーバーヘッドが増加します。プロファイリングを行って調整してください。

ロックフリーの代替手段

競合が激しい状況では、ロックフリーのデータ構造(アトミック操作、ロックフリーキュー)を検討してください。正しく記述するのははるかに難しいため、必要性を確認し、検証できる場合にのみ使用します。

簡単な確認

複数のミューテックスを一度にロックする場合、どのRAIIロックを優先すべきですか?

まとめ

シンプルなクリティカルセクションにはstd::lock_guard、複数のミューテックスにはstd::scoped_lock、条件変数や手動アンロックなどの柔軟性が必要な場合にはstd::unique_lockを使用します。必ずRAIIを使用し、lock/unlockを手動で呼び出さないでください。

よくある質問

「std::mutex、lock_guard、unique_lock」レッスンは無料ですか?

はい。「std::mutex、lock_guard、unique_lock」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、C++ Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 C++ Academyコースには全4レッスンが含まれています。

「std::mutex、lock_guard、unique_lock」で何を学びますか?

mutexとRAIIによるロックヘルパーで共有状態を保護します。 ブラウザで直接実行するハンズオンコードでC++ Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

C++ Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのC++ Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「std::mutex、lock_guard、unique_lock」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このC++ Academyレッスンでコードを書いて実行できますか?

はい。すべてのC++ Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

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

  1. std::threadのjoinとdetach
  2. std::mutex、lock_guard、unique_lock
  3. 条件変数とワーカーパターン
  4. std::asyncとstd::futureの基本
← C++ Academyに戻る