一、并发编程概述:并发与并行的区别、多线程的应用场景、C++11线程库简介

各位同学,咱们今天聊聊并发编程的入门话题。说实话,我刚开始接触这个领域时,也被一堆概念绕得头晕。但别担心,我会用最直白的方式讲清楚。

1.1 并发 vs 并行:别再傻傻分不清

这两个词,我见过太多人混着用。包括我自己,刚入行时也闹过笑话。

并发(Concurrency),说白了就是「看起来同时做多件事」。比如你一边写代码,一边听音乐。实际上你的大脑在快速切换——写几行代码,切到音乐,再切回来。这就是并发。

并行(Parallelism),才是「真正的同时做多件事」。比如你左手敲键盘,右手拿鼠标。两个动作同时发生,互不干扰。

我打个比方:

  • 并发 = 一个人吃三个馒头,一口一口轮着吃
  • 并行 = 三个人同时吃三个馒头

嗯,这里要注意:并发是逻辑上的同时,并行是物理上的同时。单核CPU只能并发,多核CPU才能并行。

核心区别一句话:

并发是「处理多个任务的能力」,并行是「同时执行多个任务的能力」。

我在项目中遇到过这样一个场景:一个网络服务器要处理上千个客户端连接。如果用并行思路,开上千个线程?系统直接崩了。但用并发思路,用事件循环+线程池,轻松搞定。这就是并发设计的魅力。

1.2 多线程的应用场景:什么时候该用?

你可能会问:我写个简单的计算器,需要多线程吗?当然不用。但有些场景,不用多线程就是跟自己过不去。

典型场景一:UI响应 + 后台计算

比如你写个图像处理软件。用户点了个「滤镜」按钮,如果直接在UI线程里算,界面就卡死了。用户会以为程序崩溃了。正确的做法:开个工作线程去算,UI线程继续响应用户操作。

典型场景二:IO密集型任务

读文件、网络请求、数据库查询……这些操作大部分时间在等待。单线程做,CPU闲着,IO也慢。多线程可以让一个线程等IO时,另一个线程继续干活。

典型场景三:计算密集型任务

视频编码、科学计算、3D渲染……这些活儿CPU越猛越好。多核CPU上,开多个线程并行算,速度翻倍。

我曾经接手过一个日志分析系统,单线程处理一天的数据要跑8小时。改成多线程后,2小时搞定。老板当场给我加了鸡腿。

我的建议:

别为了用多线程而用多线程。先问自己三个问题:

  1. 这个任务能拆成独立的小任务吗?
  2. 拆开后,有没有共享数据需要保护?
  3. 多线程带来的性能提升,值得增加复杂度吗?

如果答案都是「是」,那就大胆上。

1.3 C++11线程库简介:终于等到你

在C++11之前,写多线程简直是噩梦。Windows用CreateThread,Linux用pthread,跨平台?想都别想。

C++11终于把线程支持纳入了标准库。说实话,我等这一天等了好多年。

核心组件一览:

组件 头文件 作用
std::thread <thread> 创建和管理线程
std::mutex <mutex> 互斥锁,保护共享数据
std::lock_guard <mutex> RAII风格的锁管理
std::atomic <atomic> 原子操作,无锁编程基础
std::future <future> 异步任务,获取返回值
std::condition_variable <condition_variable> 条件变量,线程间通知

来看个最简单的例子:

#include <iostream>
#include <thread>

void hello() {
    std::cout << "Hello from thread!\n";
}

int main() {
    std::thread t(hello);  // 创建线程,执行hello函数
    t.join();              // 等待线程结束
    return 0;
}

就这么几行,一个跨平台的多线程程序就写好了。放在以前,你得写一堆平台相关的代码。

避坑指南:

我曾经犯过一个低级错误:忘记调用join()或detach(),导致程序崩溃。记住:每个std::thread对象在销毁前,必须明确是等待它(join)还是分离它(detach)。否则会触发std::terminate。

C++11线程库的设计哲学是「轻量、安全、可移植」。它没有提供线程池、读写锁这些高级工具,但提供了足够的基础构件。你可以用这些构件搭出任何你想要的东西。

我个人习惯是:能用标准库就不用第三方库。标准库的线程组件经过了全世界无数项目的检验,稳定性和可移植性都有保障。

本章知识体系

下面这张图,帮你理清本章的核心脉络:

并发编程概述:知识体系 并发 vs 并行 并发:逻辑同时 并行:物理同时 单核并发,多核并行 多线程应用场景 UI响应 + 后台计算 IO密集型任务 计算密集型任务 C++11线程库 std::thread 线程 std::mutex 互斥锁 std::atomic 原子操作 std::future 异步任务 理解概念 → 选对场景 → 用好工具

这张图把本章的三个核心主题串起来了。从左到右,从理论到实践。你想想看,搞懂并发和并行的区别,知道什么时候该用多线程,再掌握C++11提供的工具,是不是心里就有底了?

好了,这一章就聊到这儿。记住:并发编程不是炫技,而是解决实际问题的利器。下一章我们深入std::thread的细节,看看线程到底怎么创建、怎么管理、怎么安全地结束。


公众号:蓝海资料掘金营,微信 deep3321