Namensräume
Varianten
Aktionen

std::condition_variable_any::notify_one

Von cppreference.com
 
 
Bibliothek für nebenläufige Programmierung
Threads
(C++11)
(C++20)
this_thread Namespace
(C++11)
(C++11)
(C++11)
Kooperatives Beenden
Gegenseitiger Ausschluss
(C++11)
Allgemeines Sperrungsmanagement
(C++11)
(C++11)
(C++11)
(C++11)
(C++11)
Bedingungsvariablen
(C++11)
Semaphoren
Latches und Barriers
(C++20)
(C++20)
Futures
(C++11)
(C++11)
(C++11)
(C++11)
Sichere Wiederherstellung
(C++26)
Hazard Pointer
Atomare Typen
(C++11)
(C++20)
Initialisierung von atomaren Typen
(C++11)(veraltet in C++20)
(C++11)(veraltet in C++20)
Speicherordnung
(C++11)(deprecated in C++26)
Freie Funktionen für atomare Operationen
Freie Funktionen für atomare Flags
 
 
void notify_one() noexcept;
(seit C++11)

Wenn Fäden auf *this warten, hebt der Aufruf von notify_one einen der wartenden Fäden auf.

Inhalt

[bearbeiten] Parameter

(keine)

[bearbeiten] Rückgabewert

(keine)

[bearbeiten] Hinweise

Die Effekte von notify_one()/notify_all() und jeder der drei atomaren Teile von wait()/wait_for()/wait_until() (entsperren+warten, aufwecken und sperren) finden in einer einzigen Gesamtordnung statt, die als Modifikationsordnung einer atomaren Variablen betrachtet werden kann: Die Ordnung ist spezifisch für diese einzelne Bedingungsvariable. Dies macht es unmöglich, dass notify_one() beispielsweise verzögert wird und einen Thread aufweckt, der kurz nach dem Aufruf von notify_one() zu warten begonnen hat.

Der benachrichtigende Faden muss nicht die Sperre auf demselben Mutex halten wie die von den wartenden Fäden gehaltene Sperre. Tatsächlich ist dies eine Pessimierung, da der benachrichtigte Faden sofort wieder blockiert würde und darauf warten würde, dass der benachrichtigende Faden die Sperre freigibt. Einige Implementierungen (insbesondere viele Implementierungen von pthreads) erkennen diese Situation jedoch und vermeiden dieses "Beeil dich und warte"-Szenario, indem sie den wartenden Faden während des Benachrichtigungsaufrufs von der Warteschlange der Bedingungsvariable direkt in die Warteschlange des Mutex übertragen, ohne ihn aufzuwecken.

Eine Benachrichtigung unter der Sperre kann dennoch notwendig sein, wenn eine präzise Zeitplanung von Ereignissen erforderlich ist, z. B. wenn der wartende Faden das Programm beenden würde, wenn die Bedingung erfüllt ist, was zur Zerstörung der Bedingungsvariable des benachrichtigenden Fadens führen würde. Ein zufälliges Aufwachen nach dem Entsperren des Mutex, aber vor der Benachrichtigung, würde dazu führen, dass eine Benachrichtigung auf einem zerstörten Objekt aufgerufen wird.

[bearbeiten] Beispiel

#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();
}

Mögliche Ausgabe

Waiting... 
Notifying falsely...
Notifying true change...
...finished waiting; i == 1

[bearbeiten] Siehe auch

benachrichtigt alle wartenden Threads
(public member function) [bearbeiten]
C-Dokumentation für cnd_signal