c++ 提供了强大的多线程支持, 通过标准库thread和其他工具, 可以在多核处理器上并行执行多个任务
通过使用多线程, 能够在现代计算机系统中充分利用多核 CPU, 提高程序的执行效率
创建
c++ 提供 std::thread 类来实现线程创建和管理
#include <iostream>
#include <thread>
#include <unistd.h>
#include <cstdlib>
void func_1() {
for (int i = 0; i < 5; ++i) {
std::cout << "func_1" << std::endl;
sleep(1);
}
}
void func_2() {
for (int i = 0; i < 10; ++i) {
std::cout << "func_2" << std::endl;
sleep(1);
}
}
int main() {
// 实例化一个线程对象th1, 使用函数t1构造, 然后该线程就开始执行
std::thread th1(func_1);
std::thread th2(func_2);
// 必须join或detach, 等待子线程结束主进程才可以退出
th1.join();
th2.join();
return 0;
}
运行结果
func_1
func_2
func_1
func_2
func_1
func_2
func_1
func_2
func_1
std::thread 会在构造时启动新线程, 线程会在构造后自动开始执行
join() 是主线程等待子线程执行完毕的方式; 主线程会阻塞, 直到指定的子线程完成
无参数函数
#include <iostream>
#include <thread>
void func() {
for (int i = 0; i < 10; ++i) {
std::cout << "func" << std::endl;
}
}
int main() {
std::thread t(func); // 创建线程 t 执行 func 函数
t.join(); // 等待线程 t 执行完毕
return 0;
}
std::thread 接受函数指针或可调用对象作为参数, 可以直接传递无参数的函数
含参数函数
#include <iostream>
#include <thread>
void print_num(int i) {
std::cout << "Received number: " << i << std::endl;
}
int main() {
int num = 10;
std::thread t(print_num, num); // 将参数 num 传递给线程
t.join(); // 等待线程执行完毕
return 0;
}
类成员函数
对于类的成员函数, 需要稍微注意传递对象实例和成员函数的指针
可以通过 &object_name 和成员函数指针来指定要调用的成员函数
#include <iostream>
#include <thread>
class Demo {
public:
void do_lengthy_work(int num) {
std::cout << "Working on task " << num << std::endl;
}
};
int main() {
Demo my_x; // 创建类的实例
int num = 5;
// 使用类成员函数创建线程, 传递实例和参数
std::thread t(&Demo::do_lengthy_work, &my_x, num);
t.join(); // 等待线程执行完毕
return 0;
}
类成员函数需要传递对象实例(&my_x)和成员函数的参数
使用成员函数时, 需要注意实例的生命周期, 确保实例在线程执行过程中仍然有效
同步
join
join() 用于主线程等待子线程完成
当主线程调用 join() 时, 主线程会被阻塞, 直到子线程执行完毕
std::thread t(func);
t.join(); // 主线程等待线程 t 执行完毕
detach
detach() 方法将线程从主线程中分离出来, 线程继续在后台执行
分离的线程会自动在执行完成后释放资源
使用 detach() 时, 线程的生命周期不再由主线程控制, 需要开发者自行保证线程的安全性
std::thread t(func);
t.detach(); // 主线程不等待, 线程在后台执行
- 示例
#include <iostream>
#include <thread>
void func() {
std::cout << "Thread started" << std::endl;
// 模拟任务
std::this_thread::sleep_for(std::chrono::seconds(1));
std::cout << "Thread finished" << std::endl;
}
int main() {
std::thread t(func);
// 选择是否等待子线程执行完毕
if (/*某种条件*/) {
t.join(); // 等待线程结束
} else {
t.detach(); // 不等待线程结束
}
std::cout << "Main thread finished" << std::endl;
return 0;
}
当线程完成工作时, 它会自动释放系统资源
如果线程在主线程退出之前没有正确结束, 可能会导致资源泄漏,
为了避免资源泄漏, 必须在主线程退出之前使用 join() 或 detach() 确保子线程的资源得到正确释放,