当前位置: 首页 > news >正文

第16天:C++多线程完全指南 - 从基础到现代并发编程

第16天:C++多线程完全指南 - 从基础到现代并发编程

一、多线程基础概念

1. 线程创建与管理(C++11)

#include <iostream>
#include <thread>void hello() {std::cout << "Hello from thread " << std::this_thread::get_id() << "\n";
}int main() {std::thread t1(hello);std::thread t2([](){std::cout << "Lambda thread running\n";});t1.join();  // 等待线程完成t2.join();// 输出可能交错:// Hello from thread 140245230233344// Lambda thread running
}

2. 并发与并行区别

  • 并发:交替处理多个任务(单核)
  • 并行:同时处理多个任务(多核)
// 查看硬件支持线程数
unsigned int n = std::thread::hardware_concurrency();
std::cout << n << " concurrent threads supported\n";

二、线程同步核心机制

1. 互斥锁(mutex)与RAII

#include <mutex>std::mutex mtx;
int shared_data = 0;void safe_increment() {std::lock_guard<std::mutex> lock(mtx); // 自动释放锁++shared_data;  // 临界区操作
}int main() {std::thread threads[10];for (auto& t : threads) {t = std::thread(safe_increment);}for (auto& t : threads) {t.join();}std::cout << "Final value: " << shared_data; // 正确输出10
}

2. 条件变量(生产者-消费者模式)

#include <queue>
#include <condition_variable>std::mutex mtx;
std::condition_variable cv;
std::queue<int> data_queue;void producer() {for (int i=0; i<5; ++i) {{std::lock_guard<std::mutex> lock(mtx);data_queue.push(i);}cv.notify_one();  // 通知消费者std::this_thread::sleep_for(std::chrono::milliseconds(100));}
}void consumer() {while(true) {std::unique_lock<std::mutex> lock(mtx);cv.wait(lock, []{ return !data_queue.empty(); });int data = data_queue.front();data_queue.pop();lock.unlock();std::cout << "Consumed: " << data << "\n";if(data == 4) break;}
}

三、现代C++并发特性

1. 异步任务(std::async)

#include <future>int compute(int x) {return x * x;
}int main() {auto future = std::async(std::launch::async, compute, 12);std::cout << "Result: " << future.get();  // 输出144
}

2. 原子操作(std::atomic)

#include <atomic>std::atomic<int> counter(0);  // 无需锁的线程安全计数器void increment() {for (int i=0; i<100000; ++i) {++counter;  // 原子操作}
}// 测试:两个线程同时递增
// 最终结果正确为200000

四、线程安全设计模式

1. 线程局部存储(thread_local)

thread_local int tls_var = 0;  // 每个线程独立副本void thread_func() {++tls_var;std::cout << "Thread " << std::this_thread::get_id() << ": " << tls_var << "\n";
}// 每个线程输出自己的递增结果

2. 线程池实现(C++17)

#include <vector>
#include <functional>
#include <queue>class ThreadPool {std::vector<std::thread> workers;std::queue<std::function<void()>> tasks;std::mutex queue_mutex;std::condition_variable condition;bool stop = false;public:ThreadPool(size_t threads) {for(size_t i=0; i<threads; ++i) {workers.emplace_back([this]{while(true) {std::function<void()> task;{std::unique_lock<std::mutex> lock(queue_mutex);condition.wait(lock, [this]{ return stop || !tasks.empty(); });if(stop && tasks.empty()) return;task = std::move(tasks.front());tasks.pop();}task();}});}}template<class F>void enqueue(F&& f) {{std::lock_guard<std::mutex> lock(queue_mutex);tasks.emplace(std::forward<F>(f));}condition.notify_one();}~ThreadPool() {{std::lock_guard<std::mutex> lock(queue_mutex);stop = true;}condition.notify_all();for(auto& worker : workers)worker.join();}
};

五、并发编程陷阱与调试

1. 死锁检测示例

std::mutex m1, m2;void thread_A() {std::lock_guard<std::mutex> lock1(m1);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::lock_guard<std::mutex> lock2(m2); // 可能死锁点
}void thread_B() {std::lock_guard<std::mutex> lock2(m2);std::this_thread::sleep_for(std::chrono::milliseconds(100));std::lock_guard<std::mutex> lock1(m1); // 可能死锁点
}// 解决方案:使用std::lock同时锁定多个互斥量
void safe_lock() {std::lock(m1, m2);std::lock_guard<std::mutex> lock1(m1, std::adopt_lock);std::lock_guard<std::mutex> lock2(m2, std::adopt_lock);
}

六、现代C++并发增强

1. C++20信号量(semaphore)

#include <semaphore>std::counting_semaphore<5> sem(3);  // 允许3个同时访问void limited_thread() {sem.acquire();// 访问受限资源sem.release();
}

2. 屏障(C++20 barrier)

std::barrier sync_point(3);  // 等待3个线程到达void worker() {// Phase 1sync_point.arrive_and_wait();// Phase 2(所有线程完成Phase1后继续)
}

七、常见问题解答

Q:如何检测数据竞争?

  • 使用ThreadSanitizer编译:
g++ -fsanitize=thread -g -O1 program.cpp
  • 示例输出:
WARNING: ThreadSanitizer: data race

Q:std::mutex和std::shared_mutex区别?

  • std::mutex:独占锁
  • std::shared_mutex:读写锁(C++17)
std::shared_mutex smtx;// 写操作使用独占锁
{std::unique_lock lock(smtx);data = new_value;
}// 读操作使用共享锁
{std::shared_lock lock(smtx);read_data = data;
}

八、今日总结

✅ 核心掌握:

  • 🧵 线程生命周期管理(创建、等待、分离)
  • 🔒 同步原语使用场景(mutex/atomic/condition_variable)
  • 🚧 典型并发问题检测与预防(死锁、数据竞争)
http://www.lryc.cn/news/544779.html

相关文章:

  • 中科大计算机网络原理 1.5 Internt结构和ISP
  • Windows安装sql server2017
  • 计算机网络之传输层(tcp协议)
  • 从零到一:如何用阿里云百炼和火山引擎搭建专属 AI 助手(DeepSeek)?
  • Open3D解决SceneWidget加入布局中消失的问题
  • 计算机毕业设计Python+DeepSeek-R1大模型游戏推荐系统 Steam游戏推荐系统 游戏可视化 游戏数据分析(源码+文档+PPT+讲解)
  • Linux笔记---缓冲区
  • 如何流畅访问github
  • java基础+面向对象
  • Linux 检测内存泄漏方法总结
  • 本地部署deepseek大模型后使用c# winform调用(可离线)
  • Python----数据分析(Numpy:安装,数组创建,切片和索引,数组的属性,数据类型,数组形状,数组的运算,基本函数)
  • Leetcode-最大矩形(单调栈)
  • 域内委派维权
  • leetcode---LCR 140.训练计划
  • Linux基础 -- ARM 32位常用机器码(指令)整理
  • 内存中的缓存区
  • 基于 Spring Boot 的 +Vue“宠物咖啡馆平台” 系统的设计与实现
  • LeetCode 解题思路 7(Hot 100)
  • linux-Dockerfile及docker-compose.yml相关字段用途
  • deepseek部署:ELK + Filebeat + Zookeeper + Kafka
  • 微软Office 2016-2024 x86直装版 v16.0.18324 32位
  • CMake宏定义管理:如何优雅处理第三方库的宏冲突
  • 【SpringCloud】Gateway
  • Maven入门教程
  • 大数据与金融科技:革新金融行业的动力引擎
  • Autosar RTE配置-Port Update配置及使用-基于ETAS工具
  • 【AVRCP】深入理解蓝牙音频 / 视频远程控制规范:从基础到应用
  • AWS SQS跨账户访问失败排查指南
  • 算法训练(leetcode)二刷第三十八天 | 1143. 最长公共子序列、1035. 不相交的线、53. 最大子数组和、392. 判断子序列