C++ 多线程编程全解析:原理、库与实践
一、引言随着多核处理器的普及多线程编程已成为现代 C 应用程序开发的关键技能。C11 起标准库正式引入thread、mutex、condition_variable等多线程支持极大地简化了线程创建与同步操作。本篇文章将系统介绍 C 多线程编程的核心概念与实现方式涵盖线程基础、互斥锁、条件变量、线程池设计等内容并配合实战案例加深理解。二、C 多线程基础2.1 创建线程的基本方式代码语言javascriptAI代码解释cpp复制编辑#include iostream #include thread void hello() { std::cout Hello from thread!\n; } int main() { std::thread t(hello); t.join(); // 等待线程结束 }2.2 使用 Lambda 启动线程代码语言javascriptAI代码解释cpp复制编辑std::thread t([] { std::cout Hello from lambda thread!\n; }); t.join();2.3 参数传递代码语言javascriptAI代码解释cpp复制编辑void print_id(int id) { std::cout Thread ID: id \n; } std::thread t(print_id, 42); t.join();注意默认按值传递若需引用需使用std::ref()。三、线程同步机制3.1 使用互斥锁std::mutex代码语言javascriptAI代码解释cpp复制编辑#include mutex std::mutex mtx; void print_safe(int id) { std::lock_guardstd::mutex lock(mtx); // 自动加锁与释放 std::cout ID: id \n; }3.2 死锁的出现与避免死锁常见场景代码语言javascriptAI代码解释cpp复制编辑// Thread A lock(m1); lock(m2); // Thread B lock(m2); lock(m1); // 死锁解决方案统一加锁顺序或使用std::scoped_lock/std::lock。四、条件变量std::condition_variable用于线程间通信如生产者-消费者模型示例生产者-消费者模型代码语言javascriptAI代码解释cpp复制编辑#include condition_variable #include queue std::mutex mtx; std::condition_variable cv; std::queueint q; void producer() { std::unique_lockstd::mutex lock(mtx); q.push(1); cv.notify_one(); } void consumer() { std::unique_lockstd::mutex lock(mtx); cv.wait(lock, [] { return !q.empty(); }); int val q.front(); q.pop(); }五、原子操作std::atomicstd::atomicT提供无锁并发操作代码语言javascriptAI代码解释cpp复制编辑#include atomic std::atomicint counter 0; void increment() { for (int i 0; i 10000; i) { counter; } }适用于计数器、自旋锁、无锁数据结构等。六、线程池实现简析6.1 为什么需要线程池避免频繁创建/销毁线程管理任务队列提高资源利用率提高吞吐量与响应速度。6.2 简易线程池实现代码语言javascriptAI代码解释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_lockstd::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_lockstd::mutex lock(mtx); tasks.push(std::move(task)); } cv.notify_one(); } ~ThreadPool() { { std::unique_lockstd::mutex lock(mtx); stop true; } cv.notify_all(); for (auto w : workers) w.join(); } private: using Task std::functionvoid(); std::vectorstd::thread workers; std::queueTask tasks; std::mutex mtx; std::condition_variable cv; bool stop false; };七、实践案例并发文件搜索目标在多个线程中并发搜索给定目录中的所有.txt文件。示例代码代码语言javascriptAI代码解释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_guardstd::mutex lock(mtx); std::cout Found: entry.path() \n; } } } int main() { std::vectorstd::thread threads; for (auto dir : dirs) { threads.emplace_back(search_files, dir); } for (auto t : threads) t.join(); }八、线程安全与数据一致性常见错误错误情况描述竞态条件Race多线程同时写入共享变量导致结果不确定数据竞争一个线程写另一个读未同步死锁多线程互相等待资源永远阻塞解决策略使用std::mutex或std::atomic控制共享数据粒度避免在锁内调用用户回调可能造成死锁。