C++线程+匿名函数(lambda表达式) 入门
线程
我们写的程序都是一个main从上到下执行的,main怎么写,程序就怎么运行 那么这时好奇的小朋友一定想问:怎么能让程序同时做两件事呢? 聪明的五号机回答到:可以用多线程呀 这时好奇的小朋友又要问了:线程和进程有什么区别呢? 聪明的五号机又回答到:一个进程可以包括多个线程,进程之间不共享资源,线程之间共享同一个进程的资源 嗯… 也可以结合下面这幅图解释 一只怪力可以可以看成是一个进程,一只怪力有几只手就可以看成是一个进程有几个线程…(不过这里的线程是虚拟线程,有别于CPU的线程)
#include <iostream>
#include <thread>
using namespace std;
//这是线程要执行的函数
void hellofun(int i)
{
cout<<"Helloworld\t"<<i<<endl;
return;
}
//main函数相当于主线程
int main()
{
for(int i=0; i<10;i++)
{
thread THR1(hellofun, i);
THR1.join();
//THR1.detach();
}
return 0;
}
hellofun(int i)
将会被线程执行//相当于线程的main函数
thread THR1(hellofun, i)
是声明了一个叫做THR1的线程,线程将会在被声明后立即执行,hellofun
是要执行的函数名(没想到吧函数名还能这么用),函数名后面的参数就是函数的参数(hellofun的参数)
thread thrName(Fun, a, b, c, ...);
那么问题来了有时候我们想让线程一起跑(并行),有时想让它们排排队,一个一个跑(串行)又要怎么实现呢
这就涉及到线程的两个方法:
detach()
方法让线程并行,不会阻塞主线程的运行
join()
方法让线程串行,主线程会等待线程的结束
调皮的小朋友又要问了:如果两个方法都用会发生什么?
五号机:当然是报错了
调皮的小朋友又要问了:那我最多可以创建多少线程呢?
那我们把程序改一改,再跑跑看
#include <iostream>
#include <thread>//线程,C++11
using namespace std;
void hellofun(int i)
{
cout<<"Helloworld\t"<<i<<endl;
while(1);//
return;
}
int main()
{
for(int i=0; ;i++)
{
thread THR1(hellofun, i);
THR1.detach();
//THR1.join();
}
return 0;
}
好的 现在调皮的小朋友被卡死了,我们继续。 我们创建的线程都说main函数的子线程,会在main函数return后挂掉//当然有不让它挂掉的方法 线程还有很多的方法,可以实现很多功能具体的百度去吧~
匿名函数(lambda表达式)
我们创建线程必须要编写一个函数作为线程的"主函数",这就不免要有函数的声明,定义…写起来不仅麻烦,线程执行了什么内容也不能一目了然。于是C++11又送来了一个新特性:拉姆达表达式 lambda表达式。
有了lambda表达式,我们上面的程序就可以这样写了
#include <iostream>
#include <thread>
using namespace std;
int main()
{
for(int i=0; i<10; i++)
{
thread THR1([](int i){
cout<<"Helloworld\t"<<i<<endl;
}, i);
THR1.detach();
//THR1.join();
}
return 0;
}
看懂了么?我们把hellofun换成了
[](int i){cout<<"Helloworld\t"<<i<<endl;}
它没有名字(匿名)了!
匿名函数是个神奇的东西,它配合auto用似乎又可以有名字
auto fun = [](){cout<<"helloworld!"<<endl;};
fun();
//helloworld!
但是外部的变量对于匿名函数并不是可见的
int a = 666;
auto fun = [](){cout<<"helloworld!"<<a<<endl;};//这里编译器会说不知道a是什么
fun();
要想使用外部变量就要修改中括号部分: []:默认不捕获任何变量; [=]:默认以值捕获所有变量; [&]:默认以引用捕获所有变量; [x]:仅以值捕获x,其它变量不捕获; [x,y,z]:仅以值捕获x,y,z,其它变量不捕获; [&x]:仅以引用捕获x,其它变量不捕获; [=, &x]:默认以值捕获所有变量,但是x是例外,通过引用捕获; [&, x]:默认以引用捕获所有变量,但是x是例外,通过值捕获; [this]:通过引用捕获当前对象(其实是复制指针); [*this]:通过传值方式捕获当前对象;
关于lambda表达式,也可以看看这篇文章: https://www.jianshu.com/p/d686ad9de817
//C++的lambda表达式同时用到了大括号中括号小括号,真帅!