Sincronizarea Multithreading a Firelor de Execuție cu std::latch și std::barrier în C++20 în C++

Ghid complet pentru primitivele de sincronizare std::latch (numărător unidirecțional) și std::barrier (barieră fazică reutilizabilă) în C++20: coordonarea precisă a grupurilor de fire de execuție concurente fără mecanisme lente de mutex.

Sintaxă
#include <latch> | #include <barrier> | std::latch start(5); start.count_down(); start.wait();

Sincronizarea grupurilor de thread-uri prin mecanisme tradiționale (combinații de std::mutex și std::condition_variable) presupune mult cod predispus la blocaje (race conditions) și un overhead substanțial de sistem de operare. C++20 introduce două primitive hardware de înaltă eficiență:

  • std::latch: Un contor de sincronizare descrescător de unică folosință (single-use). Când contorul ajunge la zero, toate thread-urile blocate în wait() sunt eliberate instantaneu.
  • std::barrier: O barieră ciclică reutilizabilă (multi-phase). Un grup de thread-uri lucrează în etape paralele; la finalul fiecărei etape, toate thread-urile se așteaptă reciproc, se execută o funcție de callback de finalizare, iar bariera se resetează automat pentru runda următoare.
Coordonarea thread-urilor cu std::latch
#include <latch>
#include <thread>
#include <vector>
#include <print>

int main() {
    constexpr int NUMAR_WORKERS = 4;
    // Latch inițializat cu 4:
    std::latch startSemnal(NUMAR_WORKERS);

    std::vector<std::jthread> workers;
    for (int i = 0; i < NUMAR_WORKERS; ++i) {
        workers.emplace_back([&startSemnal, i]() {
            std::println("Worker-ul {} s-a initializat.", i);
            // Fiecare worker scade contorul și așteaptă ca toți ceilalți să fie gata:
            startSemnal.arrive_and_wait();
            std::println("Worker-ul {} a inceput procesarea paralela!", i);
        });
    }

    return 0;
}