随着多核处理器的普及,多线程编程成为现代 C++ 开发中不可或缺的一部分。从加速计算到后台任务处理,多线程技术在各类应用中扮演着关键角色。
本文将深入讲解 C++11 及以上标准中的多线程相关内容,包括线程创建、数据共享控制、线程同步机制,以及并发编程的设计模式和最佳实践。
C++11 标准引入 <thread>
, <mutex>
, <condition_variable>
, <future>
等头文件,正式提供原生支持的并发编程能力。
常用模块:
模块 | 功能描述 |
---|---|
<thread> | 线程对象创建、管理 |
<mutex> | 互斥锁 |
<condition_variable> | 条件变量,用于线程间通信 |
<future> | 异步操作的结果获取 |
<atomic> | 原子操作 |
cpp复制编辑#include<iostream>#include<thread>voidprintMessage() {
std::cout << "Hello from thread!" << std::endl;
}
intmain() {
std::thread t(printMessage);
t.join(); // 等待线程执行完成return0;
}
cpp复制编辑voidgreet(const std::string& name) {
std::cout << "Hello, " << name << "!" << std::endl;
}
std::thread t(greet, "Alice");
参数传递可使用值传递、引用包装器(如 std::ref
)、移动语义等。
join()
:主线程等待子线程结束detach()
:子线程独立运行,生命周期不再受主线程管理多个线程访问共享资源时,必须使用同步机制避免数据竞争和未定义行为。
cpp复制编辑std::mutex mtx;
voidcritical_section() {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁/释放// 临界区代码
}
std::lock_guard
是 RAII 风格锁管理器,推荐使用。
比 lock_guard
更灵活,可延迟锁定、手动释放等:
cpp复制编辑std::unique_lock<std::mutex> lock(mtx, std::defer_lock);
lock.lock();
// ...
lock.unlock();
死锁常因多个线程不同顺序加锁造成。解决方式:
std::lock()
同时加多个锁cpp复制编辑std::lock(mtx1, mtx2);
std::lock_guard<std::mutex> l1(mtx1, std::adopt_lock);
std::lock_guard<std::mutex> l2(mtx2, std::adopt_lock);
std::condition_variable
允许一个线程等待另一个线程发出信号。
cpp复制编辑std::mutex mtx;
std::condition_variable cv;
bool ready = false;
voidworker() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, []{ return ready; });
std::cout << "Thread resumed\n";
}
voidnotifier() {
std::this_thread::sleep_for(std::chrono::seconds(1));
{
std::lock_guard<std::mutex> lock(mtx);
ready = true;
}
cv.notify_one();
}
cv.wait()
会自动释放锁并等待,收到通知后重新获得锁继续执行。
std::async
可异步启动任务并返回 std::future
获取结果。
cpp复制编辑#include<future>intcompute() {
return42;
}
intmain() {
std::future<int> fut = std::async(compute);
int result = fut.get(); // 阻塞等待结果
}
适合任务分解与并行执行。
std::atomic
提供原子类型操作,避免锁带来的开销与死锁问题。
cpp复制编辑#include<atomic>std::atomic<int> counter(0);
voidincrement() {
for (int i = 0; i < 1000; ++i)
++counter;
}
原子变量可直接进行加减、比较交换等操作,线程安全。
fetch_add()
, fetch_sub()
compare_exchange_weak()
, compare_exchange_strong()
常使用 mutex + condition_variable
实现,有效控制缓冲区。
cpp复制编辑classThreadPool {
std::vector<std::thread> workers;
std::queue<std::function<void()>> tasks;
std::mutex queue_mutex;
std::condition_variable condition;
bool stop = false;
public:
// 构造、添加任务、析构等省略
};
线程池通过复用固定线程数,避免频繁创建销毁线程带来的开销。
std::atomic
和无锁数据结构thread_local
优化线程私有数据访问condition_variable
避免忙等(busy waiting)标准库中的 vector
、map
等容器不是线程安全的。若多个线程同时读写同一容器,必须加锁。
封装线程安全容器示例:
cpp复制编辑template<typename T>
classThreadSafeQueue {
private:
std::queue<T> data;
std::mutex mtx;
public:
voidpush(T val) {
std::lock_guard<std::mutex> lock(mtx);
data.push(std::move(val));
}
booltry_pop(T& val) {
std::lock_guard<std::mutex> lock(mtx);
if (data.empty()) returnfalse;
val = std::move(data.front());
data.pop();
returntrue;
}
};
C++20 引入 std::jthread
,更友好地支持线程生命周期自动管理:
cpp复制编辑std::jthread jt([]{
std::cout << "Auto join thread\n";
});
还支持协程(co_await
, co_yield
, co_return
),用于更高层并发模型,如异步任务流。
C++ 的多线程机制由浅入深,既可通过 std::thread
实现基础线程创建,也能借助 future
、promise
、condition_variable
等构建复杂的并发架构。对于性能关键型项目,原子操作和线程池更是不可或缺的工具。
std::thread
简化并发任务std::mutex
、condition_variable
实现线程同步std::atomic
避免加锁
文章评论(0条评论)
登录后参与讨论