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

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.lryc.cn/news/2401222.html

相关文章:

  • Vue3中Ant-design-vue的使用-附完整代码
  • k8s热更新-subPath 不支持热更新
  • Redis Sorted Set 深度解析:从原理到实战应用
  • docker中组合这几个命令来排查 import 模块失败 的问题
  • 若依框架修改模板,添加通过excel导入数据功能
  • web全栈开发学习-01html基础
  • 基于Socketserver+ThreadPoolExecutor+Thread构造的TCP网络实时通信程序
  • [Java 基础]枚举
  • 多线程环境中,如果多个线程同时尝试向同一个TCP客户端发送数据,添加同步机制
  • 【含文档+PPT+源码】基于微信小程序的旅游论坛系统的设计与实现
  • 贝叶斯优化+LSTM+时序预测=Nature子刊!
  • NodeJS全栈WEB3面试题——P3Web3.js / Ethers.js 使用
  • Quick UI 组件加载到 Axure
  • Vue3(ref与reactive)
  • Starrocks中RoaringBitmap杂谈
  • 通过ca证书的方式设置允许远程访问Docker服务
  • 涂胶协作机器人解决方案 | Kinova Link 6 Cobot在涂胶工业的方案应用与价值
  • 理解继承与组合的本质:Qt 项目中的设计选择指南
  • 新手小白使用VMware创建虚拟机安装Linux
  • 使用 PHP 和 Guzzle 对接印度股票数据源API
  • EscapeX:去中心化游戏,开启极限娱乐新体验
  • 使用PyQt5的图形用户界面(GUI)开发教程
  • STM32实战:智能环境监测站设计方案
  • 猎板硬金镀层厚度:新能源汽车高压系统的可靠性基石
  • KEYSIGHT是德科技 E5063A 18G ENA系列网络分析仪
  • VR 虚拟仿真工器具:开启医学新视界的智慧钥匙​
  • webshell管理工具、C2远控服务器流量分析
  • JavaWeb:前端工程化-TS(TypeScript)
  • unity+ spine切换武器不换皮肤解决方案
  • [java八股文][MySQL面试篇]SQL基础