std::condition_variable_any::notify_one
| void notify_one() noexcept; |
(C++11以降) | |
待機しているスレッドが*thisにある場合、notify_oneを呼び出すと、待機しているスレッドのうち1つがブロックを解除されます。
目次 |
[編集] パラメータ
(なし)
[編集] 戻り値
(なし)
[編集] 注釈
notify_one()/notify_all() と、wait()/wait_for()/wait_until() の 3 つのアトミック部分(アンロック+待機、ウェイクアップ、ロック)の効果は、単一の全順序で発生します。これは、アトミック変数の一連の 変更順序 と見なすことができます。この順序は、この個別の条件変数に固有のものです。これにより、例えば、notify_one() の呼び出しが行われた直後に待機を開始したスレッドを解除するために notify_one() が遅延することは不可能になります。
通知するスレッドは、待機しているスレッドが保持しているmutexと同じmutexをロックする必要はありません。実際、そうすることは最適化の低下につながります。なぜなら、通知されたスレッドは、通知するスレッドがロックを解除するのを待って、すぐに再びブロックされるからです。しかし、一部の実装(特に多くのpthreadsの実装)はこの状況を認識し、待機中のスレッドを条件変数のキューから、通知呼び出し内のmutexのキューに直接移動させることで、この「急いで待つ」シナリオを回避します。これは、スレッドを起こすことなく行われます。
ただし、イベントの正確なスケジューリングが必要な場合、たとえば待機中のスレッドが条件が満たされた場合にプログラムを終了し、通知するスレッドの条件変数が破壊されるような場合、ロック下での通知が必要になることがあります。mutexのロック解除後、通知前にスプリアスウェイクアップが発生すると、破壊されたオブジェクトに対して通知が呼び出されることになります。
[編集] 例
#include <chrono> #include <condition_variable> #include <iostream> #include <thread> using namespace std::chrono_literals; std::condition_variable_any cv; std::mutex cv_m; int i = 0; bool done = false; void waits() { std::unique_lock<std::mutex> lk(cv_m); std::cout << "Waiting... \n"; cv.wait(lk, []{ return i == 1; }); std::cout << "...finished waiting; i == " << i << '\n'; done = true; } void signals() { std::this_thread::sleep_for(200ms); std::cout << "Notifying falsely...\n"; cv.notify_one(); // waiting thread is notified with i == 0. // cv.wait wakes up, checks i, and goes back to waiting std::unique_lock<std::mutex> lk(cv_m); i = 1; while (!done) { std::cout << "Notifying true change...\n"; lk.unlock(); cv.notify_one(); // waiting thread is notified with i == 1, cv.wait returns std::this_thread::sleep_for(300ms); lk.lock(); } } int main() { std::thread t1(waits), t2(signals); t1.join(); t2.join(); }
実行結果の例
Waiting... Notifying falsely... Notifying true change... ...finished waiting; i == 1
[編集] 関連項目
| 待機しているすべてのスレッドに通知します (public member function) | |
| C 言語ドキュメント (cnd_signal)
| |