声明:本文内容生成自ChatGPT,目的是为方便大家了解学习作为引用到作者的其他文章中。
std::thread
是 C++11 中引入的一个类,用于创建和管理线程。它提供了一种方便的方式在程序中并行执行任务。通过 std::thread
,可以在多核处理器上并行执行代码,从而提高程序的性能,特别是在需要并发处理的情况下。
基本概念
- 线程:线程是程序执行的最小单元,多个线程可以共享同一进程的资源,但每个线程有自己独立的执行序列。
- 多线程:通过创建多个线程,可以让程序的不同部分并行执行,通常用于提升性能或响应速度。
std::thread
基本用法
cpp
#include <iostream>
#include <thread>
// 线程函数
void printMessage() {
std::cout << "Hello from thread!" << std::endl;
}
int main() {
// 创建并启动线程
std::thread t(printMessage);
// 等待线程结束
t.join();
std::cout << "Hello from main!" << std::endl;
return 0;
}
详细解析
- 创建线程 :使用
std::thread t(function)
创建一个线程,function
是线程要执行的函数。线程一旦创建,立即开始执行函数中的代码。 - 等待线程完成 (
join
) :通过t.join()
,主线程会等待子线程t
执行完成。如果没有调用join()
或detach()
,则会导致程序崩溃。 - 主线程与子线程的并行执行 :主线程和子线程可以并行运行。
join()
会阻塞主线程,直到子线程结束。
示例:带参数的线程
可以通过 std::thread
将参数传递给线程函数。
cpp
#include <iostream>
#include <thread>
void printSum(int a, int b) {
std::cout << "Sum: " << (a + b) << std::endl;
}
int main() {
std::thread t(printSum, 10, 20); // 启动线程并传递参数
t.join(); // 等待线程完成
return 0;
}
Lambda 表达式与线程
可以使用 Lambda 表达式作为线程的入口函数。
cpp
#include <iostream>
#include <thread>
int main() {
int x = 10;
// 使用 lambda 表达式启动线程
std::thread t([x]() {
std::cout << "Value of x: " << x << std::endl;
});
t.join(); // 等待线程完成
return 0;
}
分离线程 (detach
)
通过 detach()
,线程可以与主线程分离,主线程不必等待子线程结束。
cpp
#include <iostream>
#include <thread>
void detachedThread() {
std::cout << "Detached thread running!" << std::endl;
}
int main() {
std::thread t(detachedThread);
t.detach(); // 分离线程,不等待其结束
std::cout << "Main thread continues!" << std::endl;
return 0;
}
注意:分离的线程会独立运行,程序不会等待它执行完成,因此需要确保在主线程结束前,分离的线程不会访问无效的资源,否则会导致未定义行为。
多线程示例
多个线程可以同时启动,并行执行不同的任务。
cpp
#include <iostream>
#include <thread>
void task1() {
std::cout << "Task 1 running" << std::endl;
}
void task2() {
std::cout << "Task 2 running" << std::endl;
}
int main() {
std::thread t1(task1);
std::thread t2(task2);
t1.join(); // 等待 t1 完成
t2.join(); // 等待 t2 完成
std::cout << "Both threads completed!" << std::endl;
return 0;
}
线程安全和共享数据
在多线程环境中,如果多个线程同时访问或修改同一资源,就可能会发生 数据竞争 ,从而导致不可预测的行为。为此,可以使用 互斥锁(std::mutex
) 来确保线程安全。
互斥锁示例
cpp
#include <iostream>
#include <thread>
#include <mutex>
std::mutex mtx; // 定义互斥锁
int sharedData = 0;
void increment() {
for (int i = 0; i < 1000; ++i) {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁和解锁
++sharedData;
}
}
int main() {
std::thread t1(increment);
std::thread t2(increment);
t1.join();
t2.join();
std::cout << "Final value of sharedData: " << sharedData << std::endl;
return 0;
}
std::mutex
:互斥锁用于确保在同一时刻只有一个线程可以访问共享数据。std::lock_guard
:是一种RAII(资源获取即初始化)风格的机制,确保互斥锁会在作用域结束时自动释放。
常用线程操作
join()
:等待线程执行结束。detach()
:分离线程,使其独立运行。hardware_concurrency()
:返回系统支持的并发线程数。
cpp
unsigned int n = std::thread::hardware_concurrency();
std::cout << "Number of cores: " << n << std::endl;
线程注意事项
- 线程同步 :当多个线程共享资源时,必须确保对共享资源的访问是线程安全的。常用的同步工具包括
std::mutex
、std::lock_guard
等。 - 线程泄漏 :如果线程在程序退出之前没有调用
join()
或detach()
,会导致程序崩溃或产生资源泄漏。 - 线程生命周期:一个线程的生命周期应该被正确管理,防止线程在其执行完成之前被销毁或主程序退出。
总结
std::thread
提供了一种简单的多线程并发模型,能够启动、管理并行执行的任务。- 通过
join()
可以确保主线程等待子线程完成,通过detach()
可以使线程独立运行。 - 当多个线程访问共享资源时,需要使用同步机制(如
std::mutex
)来防止数据竞争。