Variables de condition et schémas de travailleurs
Coordonner les threads avec std::condition_variable et le schéma classique du groupe de travailleurs
Variables de condition et schémas de travailleurs est une leçon C++ Academy gratuite sur CoddyKit. Ceci est la leçon 3 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage C++ Academy, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours C++ Academy comprend 4 leçons au total.
Qu'est-ce qu'une variable de condition ?
Une variable de condition permet à un thread d'attendre qu'un autre thread signale qu'une condition a changé. Elle sert à coordonner les producteurs et les consommateurs.
Bases de std::condition_variable
Une variable de condition fonctionne avec un std::mutex et un prédicat. Le thread en attente libère le verrou pendant l'attente, puis le reprend à son réveil.
#include <condition_variable>
#include <mutex>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> tasks;
bool done = false;Attendre une condition
Utilisez cv.wait(lock, predicate). Cette fonction déverrouille atomiquement le mutex et met le thread en veille jusqu'à sa notification. Au réveil, elle reverrouille le mutex et vérifie le prédicat ; si celui-ci est faux, le thread se rendort.
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !tasks.empty() || done; });Notification
Le fil d’exécution producteur appelle cv.notify_one() ou cv.notify_all() après avoir modifié l’état. Le verrou doit être détenu pendant la modification de l’état.
{
std::lock_guard<std::mutex> lock(mtx);
tasks.push(42);
}
cv.notify_one();Modèle producteur-consommateur
Exemple classique : les producteurs ajoutent des tâches ; les consommateurs attendent les tâches.
void consumer() {
while (true) {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !tasks.empty() || done; });
if (done && tasks.empty()) break;
int task = tasks.front();
tasks.pop();
lock.unlock();
process(task);
}
}Réveils intempestifs
Un fil d’exécution qui attend sur une variable de condition peut se réveiller sans notification. C’est pourquoi wait prend un prédicat : il le réévalue à chaque réveil.
notify_one ou notify_all
Utilisez notify_one lorsqu’un seul thread en attente peut progresser. Utilisez notify_all lorsque les changements d’état concernent tous les threads en attente, par exemple lors d’un signal d’arrêt.
Attentes temporisées
wait_for(lock, duration) et wait_until(lock, time_point) se réveillent soit à la réception d’une notification, soit après un délai d’expiration.
if (cv.wait_for(lock, 1s, [] { return ready; })) {
/* condition met */
} else {
/* timed out */
}Squelette d’un groupe de fils d’exécution travailleurs
Modèle courant : un ensemble fixe de fils d’exécution travailleurs récupère des tâches dans une file d’attente partagée. Construisez-le avec un mutex, une variable de condition, une file d’attente et un indicateur d’arrêt atomique.
Éviter les notifications perdues
Modifiez toujours l’état partagé et appelez notify_* en détenant le mutex pendant la modification de l’état. Le libérer juste avant la notification convient, à condition de garantir l’ordre des opérations. Sinon, un thread en attente risque de manquer la notification.
std::counting_semaphore (C++20)
Pour une signalisation simple fondée sur un compteur, C++20 a ajouté std::counting_semaphore, plus simple que les variables de condition pour certains modèles.
Attention aux interblocages
Détenir plusieurs verrous pendant l’attente sur une variable de condition peut provoquer un interblocage. Acquérez les verrous dans un ordre cohérent et utilisez std::scoped_lock pour plusieurs mutex.
Vérification rapide
Pourquoi cv.wait(lock, predicate) prend-il un prédicat, même lorsque vous souhaitez simplement attendre une notification ?
Récapitulatif
Une variable de condition coordonne les fils d’exécution qui attendent un changement d’état. Utilisez wait(lock, predicate) pour gérer les réveils intempestifs, modifiez l’état sous le mutex, puis appelez notify_one ou notify_all.
Questions Fréquemment Posées
La leçon « Variables de condition et schémas de travailleurs » est-elle gratuite ?
Oui — le texte complet de « Variables de condition et schémas de travailleurs » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours C++ Academy, passe à CoddyKit PRO. Le cours C++ Academy comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Variables de condition et schémas de travailleurs » ?
Coordonner les threads avec std::condition_variable et le schéma classique du groupe de travailleurs Tu pratiques C++ Academy avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer C++ Academy ?
Aucune expérience préalable n'est requise. C++ Academy sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 3 sur 4.
Combien de temps prend la leçon « Variables de condition et schémas de travailleurs » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon C++ Academy ?
Oui. Chaque leçon C++ Academy inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- std::thread : jonction et détachement
- std::mutex, lock_guard et unique_lock
- Variables de condition et schémas de travailleurs
- Bases de std::async et std::future