std::condition_variable:: notify_one
|
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Member functions | ||||
| Notification | ||||
|
condition_variable::notify_one
|
||||
| Waiting | ||||
| Native handle | ||||
|
void
notify_one
(
)
noexcept
;
|
(depuis C++11) | |
Si des threads sont en attente sur
*
this
, l'appel à
notify_one
débloque l'un des threads en attente.
Notes
Les effets de
notify_one()
/
notify_all()
et chacune des trois parties atomiques de
wait()
/
wait_for()
/
wait_until()
(déverrouillage+attente, réveil et verrouillage) se produisent dans un ordre total unique qui peut être considéré comme
l'ordre de modification
d'une variable atomique : cet ordre est spécifique à cette variable conditionnelle individuelle. Cela rend impossible, par exemple, que
notify_one()
soit retardé et débloque un thread qui a commencé à attendre juste après l'appel à
notify_one()
ait été effectué.
Le thread notifiant n'a pas besoin de détenir le verrou sur le même mutex que celui détenu par le(s) thread(s) en attente ; en fait, cela constitue une pessimisation, puisque le thread notifié serait immédiatement bloqué à nouveau, attendant que le thread notifiant libère le verrou. Cependant, certaines implémentations (en particulier de nombreuses implémentations de pthreads) reconnaissent cette situation et évitent ce scénario de « se dépêcher puis attendre » en transférant le thread en attente de la file d'attente de la variable condition directement vers la file d'attente du mutex lors de l'appel de notification, sans le réveiller.
La notification sous verrou peut néanmoins être nécessaire lorsqu'une planification précise des événements est requise, par exemple si le thread en attente quitterait le programme si la condition est satisfaite, provoquant la destruction de la variable de condition du thread notifiant. Un réveil erroné après le déverrouillage du mutex mais avant la notification entraînerait un appel de notification sur un objet détruit.
Exemple
#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(); }
Sortie possible :
Waiting... Notifying falsely... Notifying true change... ...finished waiting; i == 1
Voir aussi
|
notifie tous les threads en attente
(fonction membre publique) |
|
|
Documentation C
pour
cnd_signal
|
|