1,引入
C++11中引入了多线程的概念,从此以后编写多线程不一定要用linux的pthread库了。从入职的两家公司看,目前也是推荐使用C++语言的多线程解决方案,而不是linux的解决方案。
C++多线程用到的头文件是 <thread>,需要注意的是,编译的时候除了制定C++标准为C++11外,还要加上-pthread选项,或者直接使用-lpthread(所以推测C++底层用的应该还是linux的pthread库吧)。
2,一个启动多线程的例子
我们启动一个新的线程去执行某个函数。分成函数无参数、值传递参数和引用传递参数3种情况。
简单来说,创建thread对象,把函数和参数作为thread对象的构造函数的参数传递进去就OK了。
#include <iostream>
#include <thread>
#include <unistd.h>
#include <string>
using namespace std;
// 无参数
void Hello() {
cout << "I am so over you, LBH." << endl;
sleep(2); // 等待两秒
return;
}
// 有参数,值传递
void HelloWho(string name) {
cout << "I am " << name << endl;
sleep(1); // 等待1秒
return;
}
// 有参数,引用传递
void GetOld(unsigned& age) {
++age;
cout << "过生日了。我今年" << age << endl;
return;
}
int main() {
cout << "I am in main thread " << endl;
string str("林碧涵");
unsigned age = 18;
// 将Hello函数放入新线程,无参数传递
thread t1(Hello); // 将hello函数放入新线程运行
// 对线程进行值传递
thread t2(HelloWho, str);
// 对线程进行引用传递
// 由于下面是在构建thread对象,如果不使用std::ref,那么进行的就是值传递
thread t3(GetOld, ref(age)); // 可以通过引用修改main中的局部变量,因为共享地址空间
t3.join();
cout << "t3返回 " << endl;
t2.join(); // 等待新线程返回
cout << "t2返回 " << endl;
t1.join();
cout << "我胡汉三又回来了, age = " << age << endl;
return 0;
}
需要做几点说明:
- join()函数表示主线阻塞直到新线程返回。当然我试过,如果新线程已经返回,主线程才调用join也没什么问题,此时join是马上返回;
- 在应用传递的例子中,我们使用了std::ref这个模板函数。因为thread t3(GetOld, ref(age))首先是在定义一个thread对象,而thread的构造函数是不知道你是引用的。所以如果不用std::ref,则实际上还是值传递。在我的编译器下,不用std::ref甚至根本编译不过去,除非你把GetOld改成值传递或者const引用;
将上述代码保存成main.cpp,编译的指令如下:
g++ main.cpp -g -Wall -std=c++11 -pthread -o main
注意“-pthread”这个选项。没有这个选项编译是无法成功的。
执行结果如下:
huangyang@狗蛋:~/code/CppConcurrency/Cp2多线程$ ./main
I am in main thread
I am so over you, LBH.
I am 林碧涵
过生日了。我今年19
t3返回
t2返回
我胡汉三又回来了, age = 19
huangyang@狗蛋:~/code/CppConcurrency/Cp2多线程$