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

cpp多线程学习

1.thread

std::thread是 C++11 引入的跨平台线程管理类,封装了操作系统的线程 API(如 pthread、Windows 线程),提供统一的线程操作接口。线程的生命周期由join()detach()控制。

thread在创建时就开始执行

join():阻塞当前线程,等待目标线程执行完毕。执行后线程资源释放,不可再次join

detach():分离线程(后台运行),无需等待。线程结束后自动释放资源(无法再join)。

2.mutex

直接调用lock()/unlock()易导致死锁(如临界区抛出异常未解锁)。C++ 提供 RAII(资源获取即初始化)包装类自动管理锁的生命周期:

std::lock_guard:构造时加锁,析构时解锁(不可手动解锁)。

std::unique_lock:构造时可选延迟加锁(std::defer_lock),支持手动解锁、转移锁所有权。

3.condition_variable

std::condition_variable是线程间通信的工具,允许一个或多个线程等待某个条件满足(由其他线程通知唤醒),避免无效的轮询等待。

与unique_lock结合使用

wait(lock):阻塞当前线程,直到被notify_one()/notify_all()唤醒(自动释放锁)。

wait(lock, predicate):带谓词的等待:仅当predicate()返回true时唤醒(避免虚假唤醒)。谓词(predicate)的作用是在被notify唤醒后检查条件是否满足,其内部等价于下述代码

while (!predicate()) {wait(lock);  // 释放锁并阻塞,直到被唤醒
}

notify_one()、notify_all():唤醒线程

4.atomic 

std::atomic<T>是模板类,用于定义原子类型,确保对其的操作是原子的(不可分割),避免多线程访问时的数据竞争。适用于int等简单基本类型

以有界缓冲区为例

#include <queue>
#include <mutex>
#include <condition_variable>template<typename T>
class BoundedBuffer {
public:explicit BoundedBuffer(size_t capacity) : capacity_(capacity) {if (capacity == 0) {throw std::invalid_argument("Buffer capacity must be greater than 0");}}// 入队操作(阻塞直到有空间)void push(T element) {std::unique_lock<std::mutex> lock(mtx_);// 等待缓冲区不满(处理虚假唤醒)not_full_.wait(lock, [this] { return queue_.size() < capacity_; });queue_.push(std::move(element));  // 使用移动语义避免拷贝not_empty_.notify_one();  // 通知可能等待的出队操作}// 出队操作(阻塞直到有元素)T pop() {std::unique_lock<std::mutex> lock(mtx_);// 等待缓冲区非空(处理虚假唤醒)not_empty_.wait(lock, [this] { return !queue_.empty(); });auto val = std::move(queue_.front());  // 使用移动语义避免拷贝queue_.pop();not_full_.notify_one();  // 通知可能等待的入队操作return val;}// 获取当前元素数量(线程安全)size_t size() const {std::lock_guard<std::mutex> lock(mtx_);return queue_.size();}private:std::queue<T> queue_;mutable std::mutex mtx_;  // mutable允许在const成员函数中加锁std::condition_variable not_full_;  // 缓冲区不满条件变量std::condition_variable not_empty_; // 缓冲区非空条件变量const size_t capacity_;  // 缓冲区最大容量
};int main() {const size_t buffer_capacity = 5;const int data_count = 10;  // 每个生产者生产10个数据BoundedBuffer<int> buffer(buffer_capacity);// 生产者线程:向缓冲区推送数据auto producer = [&buffer, data_count](int producer_id) {for (int i = 0; i < data_count; ++i) {buffer.push(producer_id * 100 + i);  // 生产数据(ID+序号)std::this_thread::sleep_for(std::chrono::milliseconds(50));  // 模拟生产耗时}};// 消费者线程:从缓冲区取出数据auto consumer = [&buffer, data_count](int consumer_id) {for (int i = 0; i < data_count; ++i) {int val = buffer.pop();  // 消费数据(阻塞直到有数据)std::cout << "Consumer " << consumer_id << " popped: " << val << std::endl;}};// 创建线程std::vector<std::thread> threads;threads.emplace_back(producer, 1);  // 生产者1threads.emplace_back(producer, 2);  // 生产者2threads.emplace_back(consumer, 1);  // 消费者1threads.emplace_back(consumer, 2);  // 消费者2// 主线程等待所有线程完成(join)for (auto& t : threads) {if (t.joinable()) {  // 避免重复join(如线程已detach)t.join();        // 阻塞主线程,直到所有生产者/消费者完成}}std::cout << "All threads completed." << std::endl;return 0;
}

http://www.xdnf.cn/news/12009.html

相关文章:

  • 无人机光纤FC接口模块技术分析
  • [华为eNSP] 在eNSP上实现IPv4地址以及IPv4静态路由的配置
  • 融智学的数学基础,通过微分几何的纤维丛结构,构建理论框架模型包含生物层、动物层、心智层、人造物层和人格层五个维度
  • C++算法训练营 Day7 哈希表及双指针
  • 聊聊FlaUI:让Windows UI自动化测试优雅起飞!
  • Deepin 安装 Nginx
  • (eNSP)配置WDS手拉手业务
  • .NET 生态中的 MCP 项目及技术分析
  • 那些Java 线程中断的实现方式
  • 单锁与分布式锁
  • AI工程师的武器库:核心技术与实战案例
  • MCP与检索增强生成(RAG):AI应用的强大组合
  • 《Coevolutionary computation and its application》协同演化及其应用中文对照·第一章
  • 告别无效号码,精准营销从空号过滤开始
  • 固定ip和非固定ip的区别是什么?如何固定ip地址
  • Lifecycle 核心原理面试回答
  • DeepSwiftSeek 开源软件 |用于 DeepSeek LLM 模型的 Swift 客户端 |轻量级和高效的 DeepSeek 核心功能通信
  • FTPS、HTTPS、SMTPS以及WebSockets over TLS的概念及其应用场景
  • 部署SD-WAN与现有网络架构的兼容性分析:如何实现平滑集成与避免设备浪费?
  • 夏普比率(Sharpe ratio)​
  • SSL安全证书怎么安装?
  • 数据湖是什么?数据湖和数据仓库的区别是什么?
  • 记一次运行spark报错
  • 【Linux】编译器gcc/g++及其库的详细介绍
  • NumPy 2.x 完全指南【二十四】结构化数组
  • Springboot——整合websocket并根据type区别处理
  • 【25软考网工】第十章 网络规划与设计(1)综合布线
  • 【HarmonyOS 5】生活与服务开发实践详解以及服务卡片案例
  • vue源码解析——diff算法
  • Golang——7、包与接口详解