ProgrammingC++マルチスレッド/サーバー開発者

C++のマルチスレッド処理において考慮すべきポイントは何ですか?std::mutex、std::lock_guard、std::unique_lockの違いを説明し、スレッドの安全な使用例を示してください。

Hintsage AIアシスタントで面接を突破

回答

現代のC++(C++11以降)では、マルチスレッド処理のための豊富なツールが存在します:std::thread、ミューテックスおよびリソースへのアクセスを管理するためのさまざまなラッパーオブジェクト。スレッド間の安全な相互作用には、以下のコンポーネントの理解が必要です:

  • std::mutex — アクセスの同期のための基本的なロックプリミティブ。明示的なlock/unlockが必要です。
  • std::lock_guard — ミューテックスに対するRAIIラッパーで、スコープへの入出時に自動的にミューテックスを取得・解放します。
  • std::unique_lock — より汎用的なRAIIラッパーで、手動でロック/アンロックでき、ミューテックスの所有権をスレッド間で移動したり、condition_variableを使用したりできます。

レース状態を避けるためには、可能な限りRAIIラッパーを使用してください。同じミューテックスを再度取得しようとするとデッドロックにつながるため注意が必要です(再帰的ミューテックスでない限り)。

正しい使用例:

#include <iostream> #include <mutex> #include <thread> std::mutex mtx; void printThreadSafe(int id) { std::lock_guard<std::mutex> lock(mtx); std::cout << "スレッド " << id << std::endl; } int main() { std::thread t1(printThreadSafe, 1); std::thread t2(printThreadSafe, 2); t1.join(); t2.join(); }

意地悪な質問

std::lock_guardstd::mutexを使用してstd::condition_variableによる条件同期を実装できますか?

回答: いいえ!std::condition_variableを使うためには必ずstd::unique_lockstd::mutexが必要です。なぜなら、lock_guardはロックの制御(たとえば、一時的に解放する— unlock — し、再度取得する必要がある)を行うメソッドを提供しないからです。

例:

std::mutex mtx; std::condition_variable cv; bool ready = false; void waitForEvent() { std::unique_lock<std::mutex> lock(mtx); cv.wait(lock, []{return ready;}); // その後の処理 }

トピックの詳細を知らないことで発生した実際のエラーの例


逸話

プロジェクトでは手動でmtx.lock()/mtx.unlock()を使用していました。lock/unlockの間に例外が発生するとミューテックスがロックされたままになり、多くのスレッドが「フリーズ」しました。RAII(std::lock_guard)に置き換えたところ、問題が解決しました。


逸話

std::condition_variableで通知を行う際にstd::unique_lockの代わりにstd::lock_guardを使用しました。その結果、新しいコンパイラではコードがコンパイルされず、古いコンパイラではAPIの不整合のためにランタイムアサートが発生しました。


逸話

std::lock_guardのunlock()を呼び出して「手動」のミューテックスアクセス制御を行っていました。これにより、異なるコンパイラで未定義の動作が発生し、アプリケーションがクラッシュすることもありました。lock_guardはマニュアルリリースをサポートしておらず、unique_lockへの移行が必要であることが理解されました。