在C++20中,std::latch
是并发编程中的一个重要工具(C++17中是std::experimental::latch
),它提供了一个同步原语,使得一组线程可以等待直到某个事件被一定数量的线程观察到后才能继续执行。这是通过一个计数器来实现的,该计数器在std::latch
对象构造时被初始化,并且每次调用count_down()
会将计数器减1,直到计数器为0,此时所有调用wait()
或者尝试通过try_wait()
检查计数器状态的线程都将被解除阻塞并允许继续执行。
std::latch
特别适用于那些需要等待多个事务完成后才能继续执行的场景,比如并行算法的不同部分需要在继续之前同步完成状态,或者在启动时,程序需要等待多个资源加载完成后才能继续。
以下是std::latch
的基本用法示例代码:
#include <latch>
#include <iostream>
#include <thread>
// 假设我们需要同步启动5个线程执行任务
const int numberOfThreads = 5;
// 初始化一个计数器为5的latch
std::latch latch(numberOfThreads);
void worker(int id) {
std::this_thread::sleep_for(std::chrono::seconds(1)); // 模拟任务执行
std::cout << "Worker " << id << " completed.\n";
// 线程完成工作,减少latch的计数
latch.count_down();
}
int main() {
std::thread threads[numberOfThreads];
// 启动所有线程
for (int i = 0; i < numberOfThreads; ++i) {
threads[i] = std::thread(worker, i);
}
// 主线程等待所有的工作线程完成
latch.wait();
std::cout << "All workers completed.\n";
// 等待所有线程结束
for (auto& t : threads) {
t.join();
}
return 0;
}
在这个例子中,主线程创建并启动了5个工作线程,每个工作线程在完成其任务后都会通过count_down()
减少latch
的计数。主线程通过调用wait()
挂起,直到latch
的计数减至0,这时它继续执行。这样就确保了主线程在所有工作线程完成后再继续执行。
需要注意的是,与std::barrier
不同,std::latch
是单次使用的,一旦计数器达到0,就不能再重置计数器的值。这意味着每个std::latch
对象只能同步一组特定的操作;如果需要再次同步,就需要创建一个新的std::latch
实例。