随着多核处理器的普及,多线程编程已成为现代 C++ 应用程序开发的关键技能。C++11 起,标准库正式引入 <thread>
、<mutex>
、<condition_variable>
等多线程支持,极大地简化了线程创建与同步操作。
本篇文章将系统介绍 C++ 多线程编程的核心概念与实现方式,涵盖线程基础、互斥锁、条件变量、线程池设计等内容,并配合实战案例加深理解。
cpp复制编辑#include <iostream>
#include <thread>
void hello() {
std::cout << "Hello from thread!\n";
}
int main() {
std::thread t(hello);
t.join(); // 等待线程结束
}
cpp复制编辑std::thread t([] {
std::cout << "Hello from lambda thread!\n";
});
t.join();
cpp复制编辑void print_id(int id) {
std::cout << "Thread ID: " << id << "\n";
}
std::thread t(print_id, 42);
t.join();
注意: 默认按值传递,若需引用,需使用
std::ref()
。
std::mutex
cpp复制编辑#include <mutex>
std::mutex mtx;
void print_safe(int id) {
std::lock_guard<std::mutex> lock(mtx); // 自动加锁与释放
std::cout << "ID: " << id << "\n";
}
死锁常见场景:
cpp复制编辑// Thread A
lock(m1);
lock(m2);
// Thread B
lock(m2);
lock(m1); // 死锁
解决方案:统一加锁顺序或使用 std::scoped_lock
/ std::lock
。
std::condition_variable
用于线程间通信(如生产者-消费者模型):
cpp复制编辑#include <condition_variable>
#include <queue>
std::mutex mtx;
std::condition_variable cv;
std::queue<int> q;
void producer() {
std::unique_lock<std::mutex> lock(mtx);
q.push(1);
cv.notify_one();
}
void consumer() {
std::unique_lock<std::mutex> lock(mtx);
cv.wait(lock, [] { return !q.empty(); });
int val = q.front(); q.pop();
}
std::atomic
std::atomic<T>
提供无锁并发操作:
cpp复制编辑#include <atomic>
std::atomic<int> counter = 0;
void increment() {
for (int i = 0; i < 10000; ++i) {
counter++;
}
}
适用于:计数器、自旋锁、无锁数据结构等。
cpp复制编辑class ThreadPool {
public:
ThreadPool(size_t n) {
for (size_t i = 0; i < n; ++i) {
workers.emplace_back([this] {
while (true) {
Task task;
{
std::unique_lock<std::mutex> lock(this->mtx);
this->cv.wait(lock, [this] {
return stop || !tasks.empty();
});
if (stop && tasks.empty()) return;
task = std::move(tasks.front()); tasks.pop();
}
task();
}
});
}
}
void enqueue(Task task) {
{
std::unique_lock<std::mutex> lock(mtx);
tasks.push(std::move(task));
}
cv.notify_one();
}
~ThreadPool() {
{
std::unique_lock<std::mutex> lock(mtx);
stop = true;
}
cv.notify_all();
for (auto &w : workers) w.join();
}
private:
using Task = std::function<void()>;
std::vector<std::thread> workers;
std::queue<Task> tasks;
std::mutex mtx;
std::condition_variable cv;
bool stop = false;
};
在多个线程中并发搜索给定目录中的所有 .txt
文件。
cpp复制编辑void search_files(const std::string& path) {
for (const auto& entry : std::filesystem::directory_iterator(path)) {
if (entry.is_regular_file() &&
entry.path().extension() == ".txt") {
std::lock_guard<std::mutex> lock(mtx);
std::cout << "Found: " << entry.path() << "\n";
}
}
}
int main() {
std::vector<std::thread> threads;
for (auto& dir : dirs) {
threads.emplace_back(search_files, dir);
}
for (auto& t : threads) t.join();
}
错误情况 | 描述 |
---|---|
竞态条件(Race) | 多线程同时写入共享变量,导致结果不确定 |
数据竞争 | 一个线程写,另一个读,未同步 |
死锁 | 多线程互相等待资源,永远阻塞 |
std::mutex
或 std::atomic
;
C++20 引入了协程(coroutine),提供比线程更轻量级的异步编程模型。配合 co_await
、co_yield
等关键词,可实现高性能的并发系统,如事件驱动服务器、网络框架等。
cpp复制编辑task<> do_work() {
co_await some_async_operation();
co_return;
}
技术点 | 适用场景 |
---|---|
std::thread | 直接线程创建 |
std::mutex | 共享资源保护 |
std::condition_variable | 消息同步(如生产者消费者) |
std::atomic | 高性能无锁计数器 |
线程池 | 大量任务并发处理 |
多线程编程不仅需要掌握语法和库函数,更重要的是理解并发模型、数据一致性、资源调度等底层机制。建议读者动手实现一个线程池、并发任务队列,亲自体验并发的魅力。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。