C++线程一次创建 多次使用 避开循环场景中 线程多次创建销毁的开销
Posted Zetaa
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++线程一次创建 多次使用 避开循环场景中 线程多次创建销毁的开销相关的知识,希望对你有一定的参考价值。
使用场景举例:一百万次循环,每次循环中需要对两个一千万维度的向量进行内积运算。注意,可能是由于某种原因(比如是迭代算法),该场景必须顺序执行一百万次循环。在这种场景下,希望使用多线程进行计算加速,具体就是对每次一循环中的计算进行多线程计算。具体地,主线程将每一次循环中的两个一千万维度向量的内积运算切割为5个二百万维度的子向量分别交由5个子线程进行内积运算,得到五个子向量内积。然后主线程拿到5个子向量内积,对这5个值进行求和,结果即为原始的两个一千万维度向量的内积结果。然后进行下一轮循环…。
下面的代码中有三个填空部分,分别是:1)主线程在唤醒子线程之前的准备工作的代码,2)子线程干活具体内容的代码,3)主线程在一轮循环中子线程全部结束后(只是一轮)后的处理工作的代码。
// 线程一次创建,多次使用
#include <iostream> // std::cout
#include <thread> // std::thread
#include <mutex> // std::mutex, std::unique_lock
#include <condition_variable> // std::condition_variable
#include <chrono>
#include <vector>
using namespace std;
const int numOfThreads = 4; // 子线程总数量
std::mutex mtx[numOfThreads]; // 主线程唤醒子线程的锁
std::mutex mtx_main[numOfThreads]; // 子线程唤醒主线程的锁
std::condition_variable cv_main[numOfThreads];//子线程唤醒主线程的条件变量
std::condition_variable cv[numOfThreads];//主线程唤醒子线程的条件变量
bool ready[numOfThreads] = false ;// 主线程设置,子线程查看的标记
bool ready_main[numOfThreads] = false ;// 子线程设置,主线程查看的标记
volatile bool done = false;// 主线程设置,子线程查看的标记。具体用于表示主线程总体任务是否结束
void print_id(int id)
while (1)
std::unique_lock<std::mutex> lck(mtx[id]);// 用一个mutex锁创建一个 unique_lock
if (done) break; // done的值由主线程设置,done=true 则结束子线程
while (!ready[id]) cv[id].wait(lck);// 等待唤醒
if (done) break; // 双重保险,否则可能发生死锁,暂不明原因。 done的值由主线程设置,done=true 则结束子线程
/*
... 这里写线程干活的代码
*/
//std::this_thread::sleep_for(std::chrono::milliseconds(1));// 当前线程睡眠
ready[id] = false;
ready_main[id] = true;
cv_main[id].notify_one();
int main()
vector<thread> threads;
for (int i = 0; i < numOfThreads; ++i)// 创建线程
threads.push_back(thread(print_id, i));
int n = 400; // 线程1次创建,重复使用 n 次
int cnt = 0; // 计数器
while (cnt < n)
/*
... 这里写唤醒子线程的准备工作的代码
*/
for (int i = 0; i < numOfThreads; i++) // 唤醒子线程
ready[i] = true;
cv[i].notify_one();
for (int i = 0; i < numOfThreads; i++) //主线程通过阻塞等待本轮所有线程执行完毕
std::unique_lock<std::mutex> lck(mtx_main[i]);
while (!ready_main[i]) cv_main[i].wait(lck);// 等待 第 i 个线程唤醒
/*
... 这里写一轮子线程全部执行完成后的处理工作
*/
cnt++;
done = true;// 主线程任务完成
for (int i = 0; i < numOfThreads; i++) //双重保险,否则可能发生死锁,暂不明原因。 唤醒子线程
ready[i] = true;
cv[i].notify_one();
for (auto& th : threads) th.join(); // 等待所有线程结束
cout << "everything done" << endl;
return 0;
以上是关于C++线程一次创建 多次使用 避开循环场景中 线程多次创建销毁的开销的主要内容,如果未能解决你的问题,请参考以下文章