Namensräume
Varianten
Aktionen

std::condition_variable

Von cppreference.com
< cpp‎ | thread
 
 
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
condition_variable
(C++11)
(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
 
 
Definiert im Header <condition_variable>
class condition_variable;
(seit C++11)

std::condition_variable ist ein Synchronisationsprimitiv, das zusammen mit einem std::mutex verwendet wird, um einen oder mehrere Threads zu blockieren, bis ein anderer Thread sowohl eine geteilte Variable (die Bedingung) modifiziert als auch die std::condition_variable benachrichtigt.

Der Thread, der die geteilte Variable modifizieren möchte, muss

  1. Einen std::mutex erwerben (typischerweise über std::lock_guard).
  2. Die geteilte Variable modifizieren, während der Lock gehalten wird.
  3. notify_one oder notify_all auf der std::condition_variable aufrufen (kann nach der Freigabe des Locks erfolgen).

Selbst wenn die geteilte Variable atomar ist, muss sie unter Besitz des Mutex modifiziert werden, um die Modifikation korrekt an den wartenden Thread zu publizieren.

Jeder Thread, der auf eine std::condition_variable warten möchte, muss

  1. Einen std::unique_lock<std::mutex> auf dem Mutex erwerben, der zum Schutz der geteilten Variable verwendet wird.
  2. Eine der folgenden Aktionen ausführen
  1. Die Bedingung prüfen, falls sie bereits aktualisiert und benachrichtigt wurde.
  2. wait, wait_for oder wait_until auf der std::condition_variable aufrufen (gibt den Mutex atomar frei und pausiert die Thread-Ausführung, bis die Bedingungsvariable benachrichtigt wird, ein Timeout abläuft oder ein spuriöser Aufruf auftritt; gibt dann den Mutex atomar vor der Rückgabe zurück).
  3. Die Bedingung prüfen und mit dem Warten fortfahren, wenn sie nicht erfüllt ist.
or
  1. Die prädikative Überladung von wait, wait_for und wait_until verwenden, die dieselben drei Schritte ausführt.

std::condition_variable funktioniert nur mit std::unique_lock<std::mutex>, was auf einigen Plattformen maximale Effizienz ermöglicht. std::condition_variable_any bietet eine Bedingungsvariable, die mit jedem BasicLockable-Objekt funktioniert, wie z. B. std::shared_lock.

Bedingungsvariablen erlauben die gleichzeitige Ausführung der Memberfunktionen wait, wait_for, wait_until, notify_one und notify_all.

Die Klasse std::condition_variable ist ein StandardLayoutType. Sie ist nicht CopyConstructible, MoveConstructible, CopyAssignable oder MoveAssignable.

Inhalt

[bearbeiten] Geschachtelte Typen

Name Definition
native_handle_type implementierungsdefiniert

[bearbeiten] Memberfunktionen

konstruiert das Objekt
(public member function) [bearbeiten]
destruiert das Objekt
(public member function) [bearbeiten]
operator=
[gelöscht]
nicht kopierbar
(public member function) [bearbeiten]
Benachrichtigung
benachrichtigt einen wartenden Thread
(public member function) [bearbeiten]
benachrichtigt alle wartenden Threads
(public member function) [bearbeiten]
Warten
blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird
(public member function) [bearbeiten]
blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird oder nach Ablauf der angegebenen Timeout-Dauer
(public member function) [bearbeiten]
blockiert den aktuellen Thread, bis die Bedingungsvariable geweckt wird oder bis der angegebene Zeitpunkt erreicht ist
(public member function) [bearbeiten]
Native handle
gibt den nativen Handle zurück
(public member function) [bearbeiten]

[bearbeiten] Beispiel

std::condition_variable wird in Kombination mit einem std::mutex verwendet, um die Kommunikation zwischen Threads zu erleichtern.

#include <condition_variable>
#include <iostream>
#include <mutex>
#include <string>
#include <thread>
 
std::mutex m;
std::condition_variable cv;
std::string data;
bool ready = false;
bool processed = false;
 
void worker_thread()
{
    // wait until main() sends data
    std::unique_lock lk(m);
    cv.wait(lk, []{ return ready; });
 
    // after the wait, we own the lock
    std::cout << "Worker thread is processing data\n";
    data += " after processing";
 
    // send data back to main()
    processed = true;
    std::cout << "Worker thread signals data processing completed\n";
 
    // manual unlocking is done before notifying, to avoid waking up
    // the waiting thread only to block again (see notify_one for details)
    lk.unlock();
    cv.notify_one();
}
 
int main()
{
    std::thread worker(worker_thread);
 
    data = "Example data";
    // send data to the worker thread
    {
        std::lock_guard lk(m);
        ready = true;
        std::cout << "main() signals data ready for processing\n";
    }
    cv.notify_one();
 
    // wait for the worker
    {
        std::unique_lock lk(m);
        cv.wait(lk, []{ return processed; });
    }
    std::cout << "Back in main(), data = " << data << '\n';
 
    worker.join();
}

Ausgabe

main() signals data ready for processing
Worker thread is processing data
Worker thread signals data processing completed
Back in main(), data = Example data after processing

[bearbeiten] Siehe auch

bietet eine Bedingungsvariable, die mit jedem Sperrtyp verbunden ist
(Klasse) [bearbeiten]
(C++11)
bietet grundlegende Gegenseitiger-Ausschluss-Funktionen
(Klasse) [bearbeiten]
implementiert einen streng bereichsbezogenen Mutex-Besitz-Wrapper
(Klassen-Template) [bearbeiten]
implementiert verschiebbaren Mutex-Besitz-Wrapper
(Klassenvorlage) [bearbeiten]