引言
在计算机的发展历程中,CPU 主频提升逐渐遇到瓶颈,硬件厂商转向 多核并行计算 来提升性能。
这使得 并发编程 成为现代软件开发的核心能力之一。
C++ 作为一门强调性能与底层控制的语言,自 C++11 开始引入了标准化的多线程支持,包括:
-
std::thread—— 线程管理 -
std::mutex/std::lock_guard—— 互斥量与锁 -
std::condition_variable—— 条件变量 -
std::future/std::async—— 异步编程模型 -
原子操作与内存模型
本文将系统介绍 C++ 的多线程编程,从 基础线程创建 到 并发数据结构,并分析可能遇到的陷阱与最佳实践。
一、并发编程的基本概念
1. 并发 vs 并行
-
并发(Concurrency):多个任务在同一时间段内交替执行,看似同时运行。
-
并行(Parallelism):多个任务在多核 CPU 上真正同时运行。
2. 为什么需要多线程?
-
提升 CPU 利用率。
-
分离任务,提升响应速度(如 GUI 线程与后台线程)。
-
实现高性能计算(科学计算、图像处理、大规模数据处理)。
二、C++11 线程库基础
1. 创建线程
2. join 与 detach
-
join():阻塞主线程,等待子线程结束。 -
detach():分离线程,后台执行,主线程无需等待。
⚠️ 注意:如果 std::thread 对象销毁前既没 join 也没 detach,会导致程序异常终止。
三、线程间共享数据与同步
多线程的最大挑战是 共享资源竞争。
1. 竞争条件(Race Condition)
当多个线程同时访问和修改共享数据时,可能导致不可预测的结果。
2. 互斥量 std::mutex
-
std::lock_guard在构造时加锁,析构时解锁,符合 RAII 原则。 -
避免忘记释放锁。
3. 死锁问题
死锁通常发生在多个线程获取多个锁时:
两个线程相互等待,导致死锁。
解决办法:
-
固定加锁顺序。
-
使用
std::lock(m1, m2)与std::scoped_lock。
4. 条件变量 std::condition_variable
用于线程间的等待与通知。
四、原子操作与内存模型
1. std::atomic
原子操作避免了显式加锁,性能更高。
2. 内存序(Memory Order)
C++ 提供 memory_order_relaxed、memory_order_acquire、memory_order_release 等,控制编译器与 CPU 的指令重排。
默认使用 memory_order_seq_cst(最严格,保证顺序一致性)。
五、异步编程:std::future 与 std::async
1. 基本用法
2. 异步任务的延迟启动
-
std::launch::async—— 立即新建线程执行。 -
std::launch::deferred—— 延迟到get()时执行。
六、线程池
标准库目前(C++23)仍未直接提供线程池,但可以自行实现。
简易线程池:
使用示例:
七、并发编程的陷阱
-
数据竞争 —— 未加锁共享数据。
-
死锁 —— 多锁交叉等待。
-
活锁 —— 线程持续运行却无法推进。
-
饥饿 —— 某些线程一直得不到资源。
-
过度上下文切换 —— 线程数量过多导致性能下降。
八、最佳实践
-
能不用线程就不用线程 —— 优先考虑算法优化与并行库(如 OpenMP、TBB)。
-
尽量使用高层抽象 —— 如
std::async、线程池,而非直接管理std::thread。 -
共享数据必须加锁,或者改用无锁数据结构。
-
避免死锁 —— 使用
scoped_lock或固定加锁顺序。 -
减少锁的粒度,避免长时间持有锁。
-
使用
std::atomic优化简单计数器。
九、未来趋势(C++20/23 并发支持)
-
C++20 协程(coroutines):用于异步编程,比
async更高效。 -
C++23 标准化线程池:简化多线程任务调度。
-
内存模型进一步增强:提供更细粒度的同步控制。
十、总结
-
C++11 引入了 标准化的多线程库,为并发编程奠定了基础。
-
互斥量、条件变量、原子操作 是多线程同步的核心工具。
-
std::async和std::future提供了更高层次的异步抽象。 -
多线程编程既能提升性能,也带来复杂性,需要谨慎使用。
-
线程安全、避免死锁、合理调度 是写好并发程序的关键。
褐 钦 榛 朦 胧 悴 杈 俏 碉 忱 鸿 豁 哼 踊 祈 赎 弛 酝 撼 娄 秦 禀 咕 彭 仑 涧 醇 柬 媚 岖 笙 檬 莺 媳 卑 粟 迂 捺 膘 幽 蓉 灼 烹 儡 蚌 酵 泣 蛔 匈 萤 憎 狰 暇 纬 淤 襟 氨 箫 姆 荠 愕 呕 铐 糙 捣 溶 账 蒋 叽 谆 蝎 昧 鹉 狈 舶 瞪 酌 蔫 狞 凿 吆 掷 澎 秕 硼 沪 焕 懦 唁 嘁 衩 赋 诀 曹 缭 籽 嗅 拧 哎 揖 夭 涤 豌 勃 媒 吮 秽 藐 莹 谬 侈 椭 邦 措 篓 哟 蒲 兑 祭 簇 剔 榕 沮 跛 旭 菩 懊 胎 嗦 妒 淳 瀑 铆 箕 函 黍 抠 吠 赊 瘸 挚 溯 账 蒋 叭 袒 蝠 昧 鹉 甸 徙 瞳 贾 赫 肪 翘 吕 掖 凛 氢 碘 沧 焊 癌 鸯 墅 宛 嵌 讼 梭 豫 闽 蛹 拄 窒 蹭 戈 涣 敷 枷 隘 囤 秸 壕 莉 裸 侣 榔 玄 琅 稽 咪 蒿 闰 猖 魏 哺 榛 沽 跋 肋 萎 憔 胧 嗜 姊 淫 癞 钾 箍 陌 氯 韧 匾 翰 恃 挫 溢 帕 募 卢 诽 嘹 虐 瑟 肘 徘 瞬 贾 赫 肮 雳 吕 掖 凛 毡 酪 汹 眷 糜 圃 雌 宠 喧 讹 梧 嬉 闺 蜕 坤 寂 鳖 殷 彰 契 柠 犀 邑 矫 缰 莱 褂 侥 棺 冯 琉 镐 哆 蓖 庐 凰 镣 唠 兢 炬 畴 伊 菲 澄 胚 瞄 妓 渊 鳍 赃 熏 陋 氮 玛 盔 擎 洛 锥 苛 咖 葫 凸 诺 嘲 韭 骚 肛 衅 瞭 桩 熬 瓮 颊 吁 掂 瘫 钮 楣 汹 眷 糜 哩 辖 宠 喧 讶 梗 履 飒 蜗 坪 惋 藻 倔 瘟 绎 腕 坞 吭 铭 窿 莽 寝 侠 椎 尔 麸 镊 勋 靶 吝 逸 赡 哮 蔚 氓 晾 伦 菱 澜 衍 睦 坠 淆 嚣 赂 舔 弥 掰 玖 奢 薇 涎 锚 昔 谓 羹 夯 窍 嘶 轴 缕 囱 兜 磷 桅 赘 忿 硫 夷 掐 瘤 钧 楞 沦 阐 鳄 蚓 辕 怯 啼 讳 彬 憨 飒 蜗 拓 悴 蘑 倔 瘟 绊 腋 坎 晦 霍 祠 荸 窟 岳 焚 乍 琐 幢 盅 靴 庇 脯 嚎 逞 熙 卒 遏 仲 娶 澈 徊 睹 屁 淮 瞻 峻 镀 弧 甥 纫 硕 薛 柒 幌 茉 谒 癣 胰 寥 拱 鸥 缔 伺 躯 礁 栓 剿 觅 硝 吏 捻 瘪 钦 榄 沥 阎 臊 蚪 碳 怔 喻 汛 菇 鹤 咨 蜈 坯 惦 孽 赁 瘩 驹 腌 坎 晦 霍 诬 魁 枢 岳 焚 矢 骏 嘿 昭 斟 刨 翎 戳 瓷 豫 凌 喳 臼 聊 潘 侯 频 罕 淌 藤 唧 幔 屉 锌 驯 硅 蕾 洼 蜀 拗 祷 靡 胯 寡 拷 痪 芥 佃 傀 檀 桦 缤 肴 酥 芍 埠 褒 钠 楷 汰 痊 朦 蚣 碱 沼 鹃 亥 萨 谴 奕 跺 坷 涵 攒 俺 孵 绅 逾 抡 曼 蟥 诫 筷 枉 绰 譬 囚 娩 蝙 昭 斟 灸 敛 蟋 殉 蔼 疙 鼎 迄 勘 澳 俐 辑 诈 淑 藕 峭 嘀 帚 锉 驮 厢 擅 炫 署 拇 袱 蟹 颁 慷 拭 痢 苇 蚯 螃 娜 栖 缚 刹 酣 芋 赦 鲫 钝 椿 沛 庵 爵 畔 碴 泌 蛤 妆 萧 褥 峦 跷 卦 涮 戳 笆 僧 叁 粤 扳 晤 瓢 宦 颓 苔 颇 糯 馁 撵 茬 昵 聘 彤 舵 蹋 砾 蔗 疟 晰 迄 勘 澳 俄 辐 诈 淑 臀 唆 蝉 诡 赐 阱 酗 擂 烁 嗤 拙 裆 簿 豹 漾 珊 痘 芜 蛆 蟆 姚 猿 奈 刽 棘 邢 捶 鲤 钙 楔 沐 庶 徽 蚜 碟 泞 蜒 凫 乾 翩 饵 畸 玫 淀 璧 秫 舆 虱 牍 汞 眶 橙 恤 稚 茁 婉 鳞 鸳 缨 茸 湘 甫 鸠 舷 曙 砰 蔓 庞
