学习目标:
学习 B 站 C++ 多线程学习第二节
学习内容:
学习时间:
2020.10.19
学习产出:
2.1
- 程序运行起来,生成一个进程,该进程所属的主线程开始自动运行;当主线程从main()函数返回,则整个进程执行完毕
- 主线程从main()开始执行,那么我们自己创建的线程,也需要从一个函数开始运行(初始函数),一旦这个函数运行完毕,线程也结束运行
在例子中,我们使用 myPrint() 作为初始函数。
- 整个进程是否执行完毕的标志是:主线程是否执行完,如果主线程执行完毕了,就代表整个进程执行完毕了,此时如果其他子线程还没有执行完,也会被强行终止【此条有例外,比如 Linux 中守护进程,以后会解释】
2.2
C++ 创建一个线程:
- 包含头文件 <thread>
- 写初始函数,例子中使用 myPrint() 作为初始函数
- 在main中创建 thread 实例。
注意: 有两个线程在跑,相当于整个程序中有两条线在同时走,即使一条被阻塞,另一条也能运行
2.3 代码
#include <iostream>
#include <thread>
void myPrint() {
std::cout << "My thread starts." << std::endl;
// -------------
// -------------
std::cout << "My thread ends." << std::endl;
return;
}
int main() {
// (1)创建了线程,线程执行起点(入口)是 myPrint;(2)执行线程
std::thread myThread(myPrint);
// (2)阻塞主线程并等待 myPrint 执行完,当 myPrint 执行完毕,join()就执行完毕,主线程继续往下执行
// join 意为汇合,子线程和主线程回合
myThread.join();
// 设置断点可看到主线程等待子线程的过程
// F11逐语句,就是每次执行一行语句,如果碰到函数调用,它就会进入到函数里面
// F10逐过程,碰到函数时,不进入函数,把函数调用当成一条语句执行
// (3)传统多线程程序中,主线程要等待子线程执行完毕,然后自己才能向下执行
// detach:分离,主线程不再与子线程汇合,不再等待子线程结束
// detach 后,子线程和主线程失去关联,驻留在后台,由 C++ 运行时库接管
// myThread.detach();
// (4)joinable() 判断是否可以成功使用 join() 或者 detach()
// 如果返回 true (1),证明可以调用 join() 或者 detach()
// 如果返回 false (0),证明调用过 join() 或者 detach(),join() 和 detach() 都不能再调用了
// 已经调用过一次 join(),值变为 false (0)
if (myThread.joinable()) {
std::cout << "can use join() or detach()" << std::endl;
}
else {
std::cout << "cann't use join() or detach()" << std::endl;
}
std::cout << "Hello World!" << std::endl;
return 0;
}
2.4 可执行对象
线程类参数是一个可调用对象。
一组可执行的语句称为可调用对象,C++ 中的可调用对象可以是函数、函数指针、lambda 表达式、或者重载了函数调用运算符的类对象。
a. 重载了函数调用运算符的类对象
#include <iostream>
#include <thread>
class Ta {
public:
void operator()() { // 重载了函数调用运算符的类对象
std::cout << "My thread starts." << std::endl;
//-------------
//-------------
std::cout << "My thread ends." << std::endl;
}
};
int main() {
Ta Obj_test;
std::thread myThread(Obj_test);
myThread.join();
std::cout << "Hello World!" << std::endl;
return 0;
}
2.5 lambda表达式创建线程
#include <iostream>
#include <thread>
int main() {
// lamda 表达式
auto lambdaThread = [] {
std::cout << "My thread starts." << std::endl;
//-------------
//-------------
std::cout << "My thread ends." << std::endl;
};
std::thread myThread(lambdaThread);
myThread.join();
return 0;
}