C++11标准引入了thread库,让开发者可以无需依赖第三方库就能实现多线程功能,大幅降低了并发编程的门槛。thread库封装了不同操作系统的线程操作接口,提供了统一的跨平台多线程实现方案,支持线程创建、管理、同步等核心能力。
C++ thread库基础使用
创建线程
使用std::thread类可以创建线程,构造时传入可调用对象作为线程执行的函数,线程创建后会立即开始执行。需要注意线程对象的生命周期管理,避免线程还在运行时线程对象被销毁。
#include <iostream>
#include <thread>
// 线程执行的函数
void thread_task(int num) {
std::cout << "子线程执行,参数值:" << num << std::endl;
}
int main() {
// 创建线程,传入函数和参数
std::thread t(thread_task, 10);
// 等待子线程执行完成
t.join();
std::cout << "主线程执行完成" << std::endl;
return 0;
}
线程参数传递
向线程函数传递参数时,参数会以默认方式拷贝到线程的独立内存空间中,即使原参数是引用,也不会影响外部变量。如果需要传递引用,需要使用std::ref进行包装。
#include <iostream>
#include <thread>
void modify_value(int& val) {
val += 10;
}
int main() {
int a = 5;
// 使用std::ref传递引用
std::thread t(modify_value, std::ref(a));
t.join();
std::cout << "修改后的值:" << a << std::endl; // 输出15
return 0;
}
线程分离与等待
线程有两种管理方式,join会阻塞当前线程直到子线程执行完成,detach会让子线程在后台运行,与主线程脱离关联,此时主线程结束后子线程仍会继续执行,但是无法再获取子线程的句柄。
#include <iostream>
#include <thread>
#include <chrono>
void background_task() {
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "后台任务执行完成" << std::endl;
}
int main() {
std::thread t(background_task);
// 分离线程,让其在后台运行
t.detach();
// 主线程等待3秒,确保子线程执行完成
std::this_thread::sleep_for(std::chrono::seconds(3));
return 0;
}
线程同步机制
互斥量std::mutex
多个线程同时访问共享资源时会出现数据竞争问题,使用互斥量可以保证同一时间只有一个线程访问共享资源。访问资源前加锁,访问完成后解锁,避免数据不一致。
#include <iostream>
#include <thread>
#include <mutex>
#include <vector>
std::mutex g_mutex;
int g_counter = 0;
void increment_counter() {
for (int i = 0; i < 1000; ++i) {
// 加锁
g_mutex.lock();
++g_counter;
// 解锁
g_mutex.unlock();
}
}
int main() {
std::vector<std::thread> threads;
for (int i = 0; i < 10; ++i) {
threads.emplace_back(increment_counter);
}
for (auto& t : threads) {
t.join();
}
std::cout << "最终计数器值:" << g_counter << std::endl; // 输出10000
return 0;
}
为了避免忘记解锁导致死锁,可以使用std::lock_guard自动管理互斥量的加锁解锁,它在构造时加锁,析构时自动解锁。
#include <iostream>
#include <thread>
#include <mutex>
std::mutex g_mutex;
int g_value = 0;
void safe_increment() {
// 自动加锁,离开作用域自动解锁
std::lock_guard<std::mutex> lock(g_mutex);
++g_value;
}
int main() {
std::thread t1(safe_increment);
std::thread t2(safe_increment);
t1.join();
t2.join();
std::cout << "最终值:" << g_value << std::endl; // 输出2
return 0;
}
条件变量std::condition_variable
条件变量用于线程间的通信,一个线程等待某个条件成立,另一个线程在条件成立时通知等待的线程。需要和互斥量配合使用,等待时要先获取互斥锁。
#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
std::mutex g_mutex;
std::condition_variable g_cv;
std::queue<int> g_queue;
// 生产者线程
void producer() {
for (int i = 0; i < 5; ++i) {
std::lock_guard<std::mutex> lock(g_mutex);
g_queue.push(i);
std::cout << "生产数据:" << i << std::endl;
// 通知消费者
g_cv.notify_one();
}
}
// 消费者线程
void consumer() {
for (int i = 0; i < 5; ++i) {
std::unique_lock<std::mutex> lock(g_mutex);
// 等待队列不为空的条件
g_cv.wait(lock, []{ return !g_queue.empty(); });
int val = g_queue.front();
g_queue.pop();
std::cout << "消费数据:" << val << std::endl;
}
}
int main() {
std::thread t1(producer);
std::thread t2(consumer);
t1.join();
t2.join();
return 0;
}
进阶实战:多线程计算数组求和
下面的案例会将一个大数组拆分成多个部分,每个线程计算一部分的和,最后主线程汇总所有结果,演示多线程任务拆分和结果汇总的完整流程。
#include <iostream>
#include <thread>
#include <vector>
#include <mutex>
const int ARRAY_SIZE = 10000;
const int THREAD_NUM = 4;
std::mutex sum_mutex;
int total_sum = 0;
// 线程计算数组指定区间的和
void calculate_sum(const std::vector<int>& arr, int start, int end) {
int partial_sum = 0;
for (int i = start; i < end; ++i) {
partial_sum += arr[i];
}
// 加锁汇总结果
std::lock_guard<std::mutex> lock(sum_mutex);
total_sum += partial_sum;
}
int main() {
// 初始化数组
std::vector<int> arr(ARRAY_SIZE);
for (int i = 0; i < ARRAY_SIZE; ++i) {
arr[i] = i + 1;
}
std::vector<std::thread> threads;
int step = ARRAY_SIZE / THREAD_NUM;
// 创建多个线程拆分任务
for (int i = 0; i < THREAD_NUM; ++i) {
int start = i * step;
int end = (i == THREAD_NUM - 1) ? ARRAY_SIZE : (i + 1) * step;
threads.emplace_back(calculate_sum, std::ref(arr), start, end);
}
// 等待所有线程完成
for (auto& t : threads) {
t.join();
}
// 验证结果,1到10000的和应该是50005000
std::cout << "多线程计算结果:" << total_sum << std::endl;
return 0;
}
注意事项
- 不要对同一个线程对象同时调用join和detach,会导致程序崩溃
- 使用互斥量时要避免死锁,比如多个线程按不同顺序获取多个互斥量时容易出现死锁
- 分离的线程不要访问局部变量,因为主线程结束后局部变量会被销毁,子线程访问会出现未定义行为
- 条件变量的等待要判断虚假唤醒,所以wait要传入判断条件的谓词函数
C++多线程C++_thread库并发编程线程同步修改时间:2026-07-16 15:30:50