【C++】std::condition_variableで簡単にスレッド同期【標準ライブラリ】

【C++】std::condition_variableで簡単にスレッド同期【標準ライブラリ】

std::condition_variableとは

std::condition_variable は、C++の標準ライブラリで提供されるスレッド同期のための仕組みです。 主に std::mutexstd::unique_lock を組み合わせて使われ、特定の条件が満たされるまでスレッドを待機させたり、条件が変わったことを通知するために使用されます。

基本的な使い方

std::condition_variable は、notify_one()notify_all() を用いて待機中のスレッドに通知を送ることができます。

以下は基本的な使用例です:

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker() {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; });
    std::cout << "Worker thread is running!\n";
}

int main() {
    std::thread t(worker);

    std::this_thread::sleep_for(std::chrono::seconds(1)); 
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_one();
    t.join();
    return 0;
}

上記のコードでは、cv.wait()ready 変数が true になるのを待ち、notify_one() で通知を送ることでスレッドが実行を再開します。

複数スレッドでの使用例

notify_all() を使うと、すべての待機スレッドに通知を送ることができます。

#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
#include <condition_variable>

std::mutex mtx;
std::condition_variable cv;
bool ready = false;

void worker(int id) {
    std::unique_lock<std::mutex> lock(mtx);
    cv.wait(lock, []{ return ready; });
    std::cout << "Thread " << id << " is running!\n";
}

int main() {
    std::vector<std::thread> workers;
    for (int i = 0; i < 5; ++i) {
        workers.emplace_back(worker, i);
    }

    std::this_thread::sleep_for(std::chrono::seconds(1));
    {
        std::lock_guard<std::mutex> lock(mtx);
        ready = true;
    }
    cv.notify_all();

    for (auto &t : workers) {
        t.join();
    }
    return 0;
}

スプリアスウェイクアップへの対策

スプリアスウェイクアップ(意図しない通知なしの起床)を防ぐために、cv.wait() にはラムダ関数を使うのが一般的です。

タイムアウト付きの待機

cv.wait_for()cv.wait_until() を使用すると、一定時間待機した後に処理を進めることができます。

Producer-Consumerパターンの実装

std::condition_variable は、Producer-Consumerパターンの実装によく使われます。

デッドロックを防ぐための注意点

デッドロックを防ぐためには、ロックの取得順序を固定したり、ロックの持ち時間を最小限にすることが重要です。

まとめ

std::condition_variable は、マルチスレッド環境におけるスレッド間の同期に役立ちます。 正しく使用することで、効率的なスレッド管理を実現できます。

コメントは受け付けていません。