在 `C++ 11` 之前,`C/C++` 一直是一种顺序的编程语言。顺序是指所有指令都是串行执行的,即在相同的时刻,**有且仅有单个 CPU 的程序计数器**执行代码的代码段,并运行代码段中的指令。而 C/C++ 代码也总是对应地拥有一份操作系统赋予进程的包括堆、栈、可执行的(代码)及不可执行的(数据)在内的各种内存区域。
而在 `C++ 11` 中,一个相当大的变化就是引入了多线程的支持。这使得 `C/C++` 语言在进行线程编程时,不比依赖第三方库。
## 线程的创建
用 `std::thread` 创建线程非常简单,只需要提供线程函数或函数对象即可,并且可以同时指定线程函数的参数。
```cpp
#include <thread>
#include <iostream>
#include <windows.h>
using namespace std;
void fun1() {
while (1) {
cout << __func__ << endl;
Sleep(2000); //挂起两秒,不然打印太快什么也看出不来
}
}
void fun2() {
while (1) {
cout << __func__ << endl;
Sleep(3000); //同理
}
}
int main() {
thread t1(func1); //子线程1
thread t2(func2); //子线程2
while(1) {//主线程
cout << __func__ << endl;
Sleep(1000); //同理
}
return 0;
}
```
线程还可以接收任意个数的参数:
```cpp
void fun(int a, char b, string c) {
cout << "a = " << a << endl;
cout << "b = " << b << endl;
cout << "c = " << c << endl;
}
int main() {
std::thread t(func, 1, 'a', "mike"); //子线程, 需要头文件#include <thread>
while(1); //特地写一个死循环,让程序不结束,主线程退出了也就没有输出的效果了,具体翻看之前的系统编程
return 0;
}
```
## 回收线程资源
`std::thread::join` 等待线程结束(此函数会阻塞),并回收线程资源,如果线程函数有返回值,返回值将被忽略。
```cpp
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
using namespace std;
void pause_thread(int n) {
//指定当前线程休眠一定的时间
this_thread::sleep_for(chrono::seconds(n));
cout << "pause of " << n << " seconds ended\n";
}
int main() {
cout << "Spawning 3 threads...\n";
thread t1(pause_thread, 1);
thread t2(pause_thread, 2);
thread t3(pause_thread, 3);
cout << "Done spawning threads. Now waiting for them to join:\n";
t1.join();//等待线程结束(此函数会阻塞)
t2.join();
t3.join();
cout << "All threads joined!\n";
return 0;
}
```
如果不希望线程被阻塞执行,可以调用线程的 `std::thread::detach`,将线程和线程对象分离,让线程作为后台线程去执行(守护进程)。但需要注意的是,`detach` 之后就无法在和线程发生联系了,比如 `detach` 之后就不能再通过 `join` 来等待执行完,线程何时执行完我们也无法控制,操作系统会自动回收。
```cpp
#include <iostream> // std::cout
#include <thread> // std::thread, std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
using namespace std;
void pause_thread(int n) {
this_thread::sleep_for (chrono::seconds(n));
cout << "pause of " << n << " seconds ended\n";
}
int main() {
cout << "Spawning and detaching 3 threads...\n";
thread(pause_thread,1).detach();
thread(pause_thread,2).detach();
thread(pause_thread,3).detach();
cout << "Done spawning threads.\n";
cout << "(the main thread will now pause for 5 seconds)\n";
// give the detached threads time to finish (but not guaranteed!):
while(1); //特地写一个死循环,让程序不结束
return 0;
}
```
## 获取线程ID和CPU核心数
```cpp
void GetPid() {
this_thread::sleep_for(chrono::seconds(1));//休眠1秒
cout << "pthread id = " << this_thread::get_id() << endl;//获取当前线程id
}
int main() {
thread t(GetPid);
cout << "t.get_id() = " << t.get_id() << endl;//获取线程t的id
cout << "main id = " << this_thread::get_id() << endl;//主线程id
cout << "cup num = " << thread::hardware_concurrency() << endl;//获取cpu核心数,失败返回0
t.join();//线程阻塞回收
return 0;
}
```
总体来说和之前学的 Linux 系统编程差不多,存在一些语法上的差异
C++11:线程