C++并发编程实战:同步并发操作详解
【免费下载链接】Cpp_Concurrency_In_Action 项目地址: https://gitcode.com/gh_mirrors/cp/Cpp_Concurrency_In_Action
引言
在多线程编程中,数据保护只是基础需求,线程间的同步操作同样至关重要。本文将深入探讨C++标准库提供的同步机制,帮助开发者掌握线程间协调的核心技术。
等待事件的实现方式
传统方式的局限性
初学者常采用轮询共享标志位的方式实现线程同步,例如:
while(!task_completed) {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
这种方式存在明显缺陷:
- 资源浪费:线程在等待期间持续消耗CPU资源
- 响应延迟:无法立即感知状态变化
- 潜在的竞态条件
条件变量的正确使用
C++标准库提供了std::condition_variable来解决这些问题:
std::mutex mtx;
std::condition_variable cv;
bool ready = false;
// 等待线程
std::unique_lock<std::mutex> lck(mtx);
cv.wait(lck, []{return ready;});
// 通知线程
{
std::lock_guard<std::mutex> lck(mtx);
ready = true;
}
cv.notify_one();
关键要点:
- 必须与互斥量配合使用
- 使用
wait的重载版本避免虚假唤醒 - 通知前必须先修改条件变量
一次性事件处理:Future/Promise模型
基本概念
C++11引入了std::future和std::promise来处理一次性事件:
promise:承诺提供结果的对象future:获取承诺结果的句柄
典型应用场景
std::promise<int> result_promise;
std::future<int> result_future = result_promise.get_future();
std::thread t([&]{
// 长时间计算
result_promise.set_value(42);
});
// 主线程可以继续其他工作
int result = result_future.get(); // 阻塞直到结果就绪
t.join();
异常处理
promise也可以传递异常:
try {
// 可能抛出异常的操作
} catch(...) {
result_promise.set_exception(std::current_exception());
}
超时处理机制
时间点与时间段
C++提供了两种时间表示方式:
- 时间段:
std::chrono::duration - 时间点:
std::chrono::time_point
带超时的等待操作
std::future<int> f = std::async(some_task);
// 等待最多35毫秒
if(f.wait_for(std::chrono::milliseconds(35)) == std::future_status::ready) {
// 任务完成
} else {
// 超时处理
}
高级同步模式
屏障(Barrier)
C++20引入了std::barrier,允许多个线程在某个点同步:
std::barrier sync_point(3); // 等待3个线程
std::thread t1([&]{
// 工作代码
sync_point.arrive_and_wait();
});
std::thread t2([&]{
// 工作代码
sync_point.arrive_and_wait();
});
// 主线程
sync_point.arrive_and_wait();
信号量(Semaphore)
C++20的std::counting_semaphore提供了更灵活的同步控制:
std::counting_semaphore<10> sem(3); // 最大10,初始3
sem.acquire(); // 获取信号量
// 临界区操作
sem.release(); // 释放信号量
性能优化建议
- 减少锁粒度:尽量缩小临界区范围
- 避免锁竞争:使用读写锁(
std::shared_mutex)替代互斥锁 - 无锁编程:在适当场景考虑原子操作
- 任务窃取:使用工作队列平衡负载
常见陷阱与解决方案
-
死锁:
- 总是以固定顺序获取多个锁
- 使用
std::lock或std::scoped_lock(C++17)
-
虚假唤醒:
- 总是使用谓词检查条件
- 避免简单的
while(!condition)循环
-
优先级反转:
- 合理设置线程优先级
- 使用优先级继承协议
总结
C++标准库提供了丰富的同步原语,从基本的互斥量到高级的future/promise模型,开发者应根据具体场景选择合适的工具。理解这些同步机制的工作原理和适用场景,是构建高效、可靠并发系统的关键。
通过本文介绍的技术,开发者可以:
- 实现线程间的高效协调
- 处理一次性异步事件
- 控制并发操作的执行时序
- 构建复杂的同步模式
掌握这些同步技术将显著提升多线程程序的性能和可靠性。
【免费下载链接】Cpp_Concurrency_In_Action 项目地址: https://gitcode.com/gh_mirrors/cp/Cpp_Concurrency_In_Action
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



