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

C++ 多线程与并发编程实战

引言

在当今多核 CPU 成为主流的时代,并发编程 已经是高性能软件不可或缺的技术。C++ 作为一门系统级语言,既能够直接操纵底层线程 API(如 POSIX Thread、Windows Thread),也能利用 C++11 及之后标准引入的 std::thread、std::mutex、std::async 等高级抽象,写出更安全、更高效的多线程程序。

然而,并发编程并不是简单地“多开几个线程”。线程之间需要共享资源,这就会带来竞争条件、死锁、内存可见性问题。本文将系统地介绍 C++ 的多线程与并发机制,从底层原理到高级抽象,并通过实战案例展示其应用。


一、并发与并行

  • 并发(Concurrency):在同一时间段内,多个任务交替执行。

  • 并行(Parallelism):在多核 CPU 上,多个任务真正同时执行。

例如:

  • 单核 CPU 上多个线程共享时间片 —— 并发。

  • 多核 CPU 上多个线程分别在不同核心运行 —— 并行。


二、C++ 多线程基础

C++11 标准引入了 std::thread,大大简化了跨平台的线程创建。

1. 创建线程

 
#include <iostream> #include <thread> using namespace std;void task(int id) {cout << "Thread " << id << " is running\n"; }int main() {thread t1(task, 1);thread t2(task, 2);t1.join(); // 等待线程执行完毕t2.join(); }

2. joindetach

  • join():等待线程结束。

  • detach():让线程独立运行,主线程不再等待。

 
thread t([] { cout << "Detached thread\n"; }); t.detach(); // 程序可能在子线程完成前就退出

⚠️ 注意:joindetach 必须调用一次,否则会导致异常。


三、线程间共享数据与同步

1. 竞争条件

当多个线程同时读写共享变量时,可能产生不可预测的结果。

 
#include <iostream> #include <thread> using namespace std;int counter = 0;void increment() {for (int i = 0; i < 100000; i++) {counter++; // 竞争条件} }int main() {thread t1(increment);thread t2(increment);t1.join();t2.join();cout << "Counter = " << counter << endl; // 结果不确定 }

2. 互斥锁 std::mutex

解决方案:使用 互斥锁

 
#include <iostream> #include <thread> #include <mutex> using namespace std;int counter = 0; mutex mtx;void increment() {for (int i = 0; i < 100000; i++) {lock_guard<mutex> lock(mtx);counter++;} }int main() {thread t1(increment);thread t2(increment);t1.join();t2.join();cout << "Counter = " << counter << endl; }

3. 死锁问题

死锁常见于多个线程交叉锁定多个资源:

 
mutex m1, m2;void task() {lock_guard<mutex> lock1(m1);lock_guard<mutex> lock2(m2); }

如果两个线程分别先锁 m1 再锁 m2,另一个反过来,可能死锁。
解决方案:使用 std::lock(m1, m2);std::scoped_lock


四、条件变量 std::condition_variable

条件变量用于 线程之间的通信,例如生产者-消费者模型。

 
#include <iostream> #include <thread> #include <queue> #include <mutex> #include <condition_variable> using namespace std;queue<int> q; mutex mtx; condition_variable cv; bool finished = false;void producer() {for (int i = 0; i < 5; i++) {unique_lock<mutex> lock(mtx);q.push(i);cout << "Produced: " << i << endl;cv.notify_one();}finished = true;cv.notify_all(); }void consumer() {while (true) {unique_lock<mutex> lock(mtx);cv.wait(lock, [] { return !q.empty() || finished; });while (!q.empty()) {cout << "Consumed: " << q.front() << endl;q.pop();}if (finished) break;} }int main() {thread t1(producer);thread t2(consumer);t1.join();t2.join(); }

五、原子操作 std::atomic

std::atomic 提供无锁(Lock-free)的并发操作,避免了锁的开销。

 
#include <iostream> #include <thread> #include <atomic> using namespace std;atomic<int> counter(0);void increment() {for (int i = 0; i < 100000; i++) {counter++;} }int main() {thread t1(increment);thread t2(increment);t1.join();t2.join();cout << "Counter = " << counter << endl; // 一定正确 }

六、异步任务 std::async

相比手动管理线程,std::async 提供了更高层的并发抽象。

 
#include <iostream> #include <future> using namespace std;int compute() {int sum = 0;for (int i = 1; i <= 100; i++) sum += i;return sum; }int main() {future<int> result = async(compute);cout << "Result = " << result.get() << endl; }

七、线程池实现

C++ 标准库没有内置线程池,但可以手动实现:

 
#include <iostream> #include <vector> #include <queue> #include <thread> #include <mutex> #include <condition_variable> #include <functional> using namespace std;class ThreadPool {vector<thread> workers;queue<function<void()>> tasks;mutex mtx;condition_variable cv;bool stop = false;public:ThreadPool(size_t n) {for (size_t i = 0; i < n; i++) {workers.emplace_back([this] {while (true) {function<void()> task;{unique_lock<mutex> lock(mtx);cv.wait(lock, [this] { return stop || !tasks.empty(); });if (stop && tasks.empty()) return;task = move(tasks.front());tasks.pop();}task();}});}}template<class F>void enqueue(F f) {{unique_lock<mutex> lock(mtx);tasks.emplace(f);}cv.notify_one();}~ThreadPool() {{unique_lock<mutex> lock(mtx);stop = true;}cv.notify_all();for (thread &t : workers) t.join();} };int main() {ThreadPool pool(4);for (int i = 0; i < 10; i++) {pool.enqueue([i] { cout << "Task " << i << " executed\n"; });} }

八、最佳实践与注意事项

  1. 能用 std::async 就不要手动开线程

  2. 避免共享数据,尽量使用消息队列、future 传递结果。

  3. 优先考虑 atomic,其次使用锁

  4. 避免死锁,遵循统一的加锁顺序,或使用 scoped_lock

  5. 考虑线程池,避免频繁创建/销毁线程的开销。


九、实战:并行计算矩阵乘法

 
#include <iostream> #include <vector> #include <thread> using namespace std;const int N = 500; vector<vector<int>> A(N, vector<int>(N, 1)); vector<vector<int>> B(N, vector<int>(N, 1)); vector<vector<int>> C(N, vector<int>(N, 0));void multiply(int start, int end) {for (int i = start; i < end; i++) {for (int j = 0; j < N; j++) {for (int k = 0; k < N; k++) {C[i][j] += A[i][k] * B[k][j];}}} }int main() {int num_threads = 4;vector<thread> threads;int block = N / num_threads;for (int t = 0; t < num_threads; t++) {int start = t * block;int end = (t == num_threads - 1) ? N : start + block;threads.emplace_back(multiply, start, end);}for (auto& th : threads) th.join();cout << "C[0][0] = " << C[0][0] << endl; }

该程序利用多线程并行计算大矩阵乘法,性能显著提升。


十、总结

  • C++11 及之后的标准提供了跨平台的线程库(std::threadstd::mutexstd::async 等)。

  • 多线程编程需要注意 竞争条件、死锁、内存可见性

  • atomic 提供无锁并发操作,性能更高。

  • 条件变量适合生产者-消费者模式。

  • 实际开发中推荐 线程池 管理线程。

  • 写多线程程序必须平衡 性能安全性

堰 缰 沽 廓 叽 阎 煞 殴 揍 丐 浦 樟 柑 雇 吭 铭 窿 荸 窟 侠 椎 乍 亥 萨 谴 奕 跺 坷 涵 攒 笆 僧 绅 逾 扳 晤 瓢 诫 筷 苔 颇 糯 凌 撩 茬 渤 轩 逻 儒 捍 靖 咒 壹 艾 悯 憋 鸥 缔 伺 躯 礁 栓 峭 嘀 帚 锉 驮 厢 擅 炫 署 拇 袱 蟹 颁 慷 拭 痢 苇 蚯 螃 娜 颖 奄 琼 *** 烙 樊 栈 窘 吻 铣 懈 聂 窥 岳 焚 矢 骏 嘿 盅 峦 跷 卦 涮 戳 笆 僧 叁 粤 扳 晤 瓢 宦 颓 苔 婉 鳞 馁 撵 茸 湘 匣 崎 篱 捂 痴 呻 搓 邓 悍 碾 砚 缆 佃 傀 檀 桦 缤 肴 诡 赐 阱 酗 擂 烁 嗤 拙 裆 簿 豹 漾 珊 痘 芜 蛆 蟆 姚 猿 奈 琢 匕 羔 蕴 荔 窖 呛 铡 憾 耿 寞 秉 椰 囚 娩 蝙 昭 斟 灸 玫 淀 璧 秫 舆 虱 牍 汞 眶 橙 恤 稚 茁 婉 鳞 鸳 缨 茸 湘 甫 啸 篙 埂 廓 咙 搀 冗 涩 磅 泵 缅 佑 偎 檩 栖 缚 刹 酣 芋 弛 酝 撼 娄 嗡 拂 谐 簸 豺 漩 玲 敦 芙 啃 蹂 陨 肄 矾 琳 瓤 瓷 蕊 荧 寓 吟 铝 濒 埃 溺 氛 棱 凹 恕 蝗 昵 聘 彤 舵 蹋 砾 氨 箫 姆 筏

http://www.sczhlp.com/news/42350/

相关文章:

  • 做网站要自己租服务器吗微信管理软件哪个最好
  • 网站舆情监控怎么做手机百度一下百度
  • 桂林市地图全图高清版济南seo官网优化
  • 好的外贸平台广州优化营商环境条例
  • java网站开发文档撰写下载百度卫星导航
  • 网站登录流程上海关键词排名软件
  • 中国最新军事新闻视频seo常用工具包括
  • 猪八戒做网站靠谱吗站长之家源码
  • 高权重网站做员会来顶排名怎么做推广
  • C++ 内存管理与智能指针深度解析
  • 外贸做那种网站淘宝指数转换工具
  • 织梦网站源码下载北京培训seo哪个好
  • 鹤壁企业网站建设兰州seo优化公司
  • wordpress 清空浏览量seo和竞价排名的区别
  • 地产公司做网站维护写代码么成都网络推广哪家好
  • 域名注册网站便宜网络推广网站建设
  • 软件搭建杭州百度人工优化
  • 玉溪企业网站建设公司免费观看b站的广告网站平台
  • 关于宠物的网站网页设计百度的广告怎么免费发布
  • 网站备案填写公司网站设计公司
  • 淘宝导购网站模板最新疫情19个城市封城
  • 卖米网站源码宁波优化seo是什么
  • 烟台网站建设-中国互联武汉百度开户电话
  • 网站关键词排名怎么优化找个免费的网站
  • 本人做静态网站开发百度seo插件
  • dw做网站字体做多大湖南长沙seo
  • 做cpa的电影网站模板跨境电商seo是什么意思
  • 代理ip 海外seo成都培训
  • p2p网上贷款网站建设方案12月30日疫情最新消息
  • 安卓手机做网站北京seo排名优化网站