关于std::barrier的sync_point参数取值及正确声明的技术问询
正确声明std::barrier对象的方法
首先明确std::barrier的核心构造参数规则:
- 第一个参数必须是参与屏障同步的线程总数(正整数,比如主线程+3个工作线程,总数就是4)
- 第二个参数是可选的完成阶段回调(所有线程到达屏障后自动执行的无参数、返回void的函数)
你的代码里的核心问题
- 错误地将数组
bounds作为std::barrier的第一个参数,不符合构造要求 array_sync逻辑错误:return phase;之后的代码永远不会执行,且静态变量初始化依赖的循环变量i未正确捕获array_work未正确捕获变量,线程创建时参数传递错误(work应为array_work)
修正后的代码示例
假设bounds用于划分任务区间,且需要4个线程(主线程+3个工作线程)参与同步,修正如下:
// 假设n、bounds、on_completion均已正确定义 size_t thread_count = 4; // 参与同步的线程总数,按需调整 // 修正后的完成阶段回调,正确捕获bounds auto array_sync = [&bounds]() noexcept { static size_t phase_idx = 0; auto current_phase = bounds[phase_idx]; phase_idx = (phase_idx + 1) % bounds.size(); // 循环切换阶段 // 可在此添加阶段逻辑,如参数传递、状态更新 }; // 正确声明std::barrier:第一个参数为线程数,第二个为完成回调 std::barrier sync_point(thread_count, array_sync); // 修正后的工作线程lambda,通过参数传递任务索引 auto array_work = [&](std::string name, size_t task_idx) { size_t start = bounds[task_idx + 1] * n; size_t end = bounds[task_idx + 2] * n; array_transform(start, end, num_array_1, n); sync_point.arrive_and_wait(); array_transform(start, end, num_array_1, n); sync_point.arrive_and_wait(); }; std::vector<std::thread> threads; // 循环创建线程,主线程同步执行对应任务 for (int i = 0; i <= 6; i += 2) { // 主线程处理当前区间任务 size_t main_start = bounds[i + 1] * n; size_t main_end = bounds[i + 2] * n; array_transform(main_start, main_end, num_array_1, n); // 创建工作线程,传入任务索引i threads.emplace_back(array_work, "Worker" + std::to_string(i/2), i); } // 等待所有线程结束 for (auto& thread : threads) { thread.join(); }
关键说明
std::barrier的线程数参数必须和实际调用arrive_and_wait()的线程总数一致,否则会触发死锁或未定义行为- 完成回调若需访问外部变量(如
bounds),必须通过lambda正确捕获(值捕获或引用捕获,需考虑变量生命周期) - 线程任务的区间参数应通过传递方式传入,避免依赖循环变量的引用捕获(循环变量迭代时会更新,引用捕获会导致错误)
内容的提问来源于stack exchange,提问作者Olga Puzikova
相关产品推荐
相关产品推荐

