由于单进程的处理能力差;而多CPU的、多进程的并行处理,由于进程间的切换也使得性能不佳。因此多线程并发性能够有效的解决这个问题,能够有效的克服这个问题。
本文参考视频:https://space.bilibili.com/182674044
一、thread类
在thread头文件中的thread类是对线程的描述。class thread 主要有以下的成员函数:
- join()。调用该函数可以阻塞该进程。直至线程执行结束。
- detach()。分离线程,将当前执行的线程实例和线程对象分离。线程实例执行完毕,释放掉申请的资源。
- thread类处理能够接受普通函数Object,还能够接受Lambda等callable object。
1、普通函数
void func(int a,int b)
{
cout<<"this is func thread"<<endl;
cout<<(a + b)<<endl;
}
int main()
{
thread th = thread(func(),1,2);
th.join();
cout<<"this is main thread"<<endl;
}
- 这里就是main thread和func thread,两个线程并发执行。
//运行结果
this is func thread
3
this is main thread
2、Lambda
这里使用一个测试时间的用例说明,在创建线程的时候使用Lambda。
template<class T>
void measure(T&& func)
{
using namespace std::chrono;
auto start = system_clock::now();
func();
duration<double>diff = system_clock::now() - start;
cout<<"运行了"<<diff.count()<<"second"<<endl;
}
void sum()
{
int s = 0;
for(int i = 0;i < 10000;++i
{
s += 1;
}
}
// 使用
int main()
{
measure([](){
sum();
})
}
二、使用多线程加速处理
long sum_future(int start,int end)
{
long s = 0;
for(int i = start;i < end;++i) s += i;
return s;
}
const int num = 10000000;
int main()
{
// count个线程并发
int count = 4;
measure([](){
vector<future<long>>vf;
vf.reserve(count);
for(int i = 0;i < K;++i)
{
//将num分为count部分,分给count个线程并发执行相加操作
vf.push_back(async(sum_furture,i == 0?0:(num/ count) * i,(num / count) * (i + 1)));
}
long ans = 0;
for(int i = 0;i < count;++i)
{
ans += vf[i].get();
}
cout<<ans<<endl;
});
// 使用单线程
measure([](){
long ans = sum_furture(0,num);
});
}
- 上述代码:将0-1000000分给四个线程进行并发相加操作,和一个线程执行0-10000000相加操作。运行时间上的差异。
//运行结果
49999995000000
运行了:0.009138second
49999995000000
运行了:0.025976second
- 可以看出,多个线程的并发执行能够减少运行时间。但并不是严格的4倍关系。
三、多线程的问题
由于多个线程的并发访问,共享变量,因此会出现一定的问题。
void mutex_sum(int& s)
{
for(int i = 0;i < 10000;++i) s++;
}
int main()
{
measure([](){
vector<thread>v;
int s = 0;
for(int i = 0;i < 4;++i)
{
v.emplace_back(mutex_sum,std::ref(s));
}
for(int i = 0;i < 4:++i)
{
v[i].join();
}
cout<<s<<endl;
});
return 0;
}
- 这个时候s的值并不是4个线程进行0-10000的和,即40000.结果应该比40000小。这是因为线程间交错执行for的相加。例如thread1执行i = 100了,但是thread2执行到i = 20,那么thread下一轮的i将变为20了。这就导致了和变小了。
- 解决:在for循环中加上锁。让每个线程之间进行累加时,不互相干扰。
#include<mutex>
std::mutex mux;
void mutex_sum(int& s)
{
mux.lock();
for(int i = 0;i < 10000;++i) s++;
mux.unlock();
}