← Назад ко всем вопросам

Для чего нужна std::condition_variable

1️⃣ Как кратко ответить

std::condition_variable используется для синхронизации потоков, позволяя одному или нескольким потокам ждать, пока другой поток не уведомит их о наступлении определенного события. Это позволяет эффективно управлять доступом к общим ресурсам и координировать выполнение потоков.

2️⃣ Подробное объяснение темы

std::condition_variable — это механизм синхронизации в C++, который позволяет потокам взаимодействовать друг с другом, ожидая наступления определенных условий. Он используется в многопоточных приложениях для координации работы потоков, особенно когда один поток должен ждать, пока другой поток выполнит определенные действия или изменит состояние программы.

Зачем это нужно

В многопоточных приложениях часто возникает необходимость в том, чтобы один поток ждал, пока другой поток выполнит определенные действия. Например, поток может ждать, пока другой поток не завершит запись данных в общий буфер. Использование std::condition_variable позволяет избежать активного ожидания (busy-waiting), что экономит ресурсы процессора и делает программу более эффективной.

Как это работает

std::condition_variable работает в связке с мьютексами (std::mutex). Поток, который должен ждать, блокирует мьютекс и вызывает метод wait() объекта std::condition_variable. Это освобождает мьютекс и переводит поток в состояние ожидания. Когда другой поток изменяет состояние программы и вызывает метод notify_one() или notify_all(), ожидающий поток пробуждается и может продолжить выполнение.

Пример кода

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
​
std::mutex mtx; // Мьютекс для защиты общего ресурса
std::condition_variable cv; // Условная переменная для синхронизации
bool ready = false; // Флаг, указывающий на готовность данных
​
void worker_thread() {
    std::unique_lock<std::mutex> lock(mtx); // Блокируем мьютекс
    cv.wait(lock, []{ return ready; }); // Ждем, пока ready не станет true
    // После пробуждения продолжаем выполнение
    std::cout << "Worker thread is processing data\n";
}
​
void prepare_data() {
    std::this_thread::sleep_for(std::chrono::seconds(1)); // Имитация подготовки данных
    {
        std::lock_guard<std::mutex> lock(mtx); // Блокируем мьютекс
        ready = true; // Устанавливаем флаг готовности
    }
    cv.notify_one(); // Уведомляем один из ожидающих потоков
}
​
int main() {
    std::thread worker(worker_thread); // Создаем поток-работник
    std::thread preparer(prepare_data); // Создаем поток, подготавливающий данные
​
    worker.join(); // Ожидаем завершения потока-работника
    preparer.join(); // Ожидаем завершения потока, подготавливающего данные
​
    return 0;
}

Объяснение кода

  • std::mutex mtx;: Создаем мьютекс для защиты общего ресурса.
  • std::condition_variable cv;: Создаем условную переменную для синхронизации потоков.
  • bool ready = false;: Флаг, указывающий на готовность данных.
  • worker_thread(): Функция, выполняемая в потоке-работнике. Она блокирует мьютекс и ждет, пока ready не станет true.
  • prepare_data(): Функция, имитирующая подготовку данных. После подготовки она устанавливает ready в true и уведомляет один из ожидающих потоков.
  • main(): Создает и запускает два потока, затем ожидает их завершения.

Этот пример демонстрирует, как std::condition_variable позволяет потоку-работнику ждать, пока данные не будут готовы, и как поток, подготавливающий данные, уведомляет об этом.

Тема: Многопоточность / Синхронизация
Стадия: Tech

🔒 Подпишись на бусти автора и стань Алигатором, чтобы получить полный доступ к функционалу сайта и отслеживать свой прогресс!

Твои заметки