std::condition_variable:: notify_one
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
| Notification | ||||
|
condition_variable::notify_one
|
||||
| Waiting | ||||
| Native handle | ||||
|
void
notify_one
(
)
noexcept
;
|
(C++11以降) | |
スレッドが
*
this
で待機中の場合は、
notify_one
を呼び出すことで待機中のスレッドの1つがブロック解除されます。
注記
notify_one()
/
notify_all()
の効果と、
wait()
/
wait_for()
/
wait_until()
の3つのアトミックな部分
(ロック解除+待機、ウェイクアップ、ロック)は、
変更順序
として見なせる単一の全順序で発生します:この順序は個々の条件変数に固有です。これにより、例えば
notify_one()
の呼び出しが遅延され、
notify_one()
の呼び出し直後に待機を開始したスレッドのブロックを解除するといったことが不可能になります。
通知を行うスレッドは、待機しているスレッドが保持しているものと同じミューテックスのロックを保持する必要はありません。実際、そうすることはペシミゼーション(非最適化)となります。なぜなら、通知されたスレッドは、通知を行ったスレッドがロックを解放するのを待って、直ちに再ブロックすることになるからです。しかし、一部の実装(特にpthreadsの多くの実装)ではこの状況を認識し、通知呼び出し内で待機スレッドを条件変数のキューからミューテックスのキューへ直接転送することで、スレッドを起こすことなく「急いで待つ」シナリオを回避しています。
ロック中に通知を行うことは、イベントの正確なスケジューリングが必要な場合(例えば、条件が満たされた場合に待機スレッドがプログラムを終了し、通知スレッドの条件変数を破棄する場合)には必要となることがあります。ミューテックスのアンロック後、通知前の偽の起床(spurious wakeup)が発生すると、破棄されたオブジェクトに対してnotifyが呼び出される結果となります。
例
#include <chrono> #include <condition_variable> #include <iostream> #include <thread> using namespace std::chrono_literals; std::condition_variable 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
関連項目
|
待機中のすべてのスレッドを通知する
(公開メンバ関数) |
|
|
Cドキュメント
for
cnd_signal
|
|