🎫 std::latch — одноразовый счетчик — 24 июня 2026 г. в 07:00:07.859
🎫 std::latch — одноразовый счетчик 🩹 Проблема: Главный поток должен дождаться завершения инициализации в нескольких рабочих потоках перед началом основной работы. Барьер не подходит, так как нужна одноразовая синхронизация, а не переиспользуемая. 💡 Решение: std::latch (C++20) — это одноразовый счетчик обратного отсчета. Потоки уменьшают счетчик, а другие ждут, пока он достигнет нуля. После срабатывания latch нельзя переиспользовать. ✏️ Пример кода: #include <iostream> #include <thread> #include <latch> #include <vector> void worker_init(int id, std::latch& ready_signal) { // Имитация инициализации ресурсов std::cout << "Поток " << id << " инициализируется...\n"; std::this_thread::sleep_for(std::chrono::milliseconds(100 * id)); std::cout << "Поток " << id << " готов\n"; ready_signal.count_down(); // Уменьшаем счетчик } void worker_process(int id, std::latch& start_signal) { std::cout << "Поток " << id << " ждет сигнал старта...\n"; start_signal.wait(); // Ждем пока счетчик станет 0 std::cout << "Поток " << id << " начал обработку\n"; std::this_thread::sleep_for(std::chrono::milliseconds(100)); } int main() { const int num_workers = 4; std::latch all_ready(num_workers); // Счетчик для готовности std::latch start_work(1); // Сигнал для старта std::vector<std::thread> threads; // Создаем рабочие потоки for (int i = 0; i < num_workers; ++i) { threads.emplace_back([i, &all_ready, &start_work]() { worker_init(i, all_ready); worker_process(i, start_work); }); } // Главный поток ждет готовности всех std::cout << "Главный поток ждет инициализации...\n"; all_ready.wait(); std::cout << "Все потоки готовы. Даем сигнал старта!\n"; start_work.count_down(); // Даем сигнал старта for (auto& t : threads) { t.join(); } return 0; } ‼️ Преимущества: • Простая одноразовая синхронизация множества потоков • Эффективное ожидание без активных проверок • Идеален для сценариев типа ждать «готовности всех» • Минимальные накладные расходы по сравнению с condition_variable

