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

无锁队列简易入门

告别阻塞,拥抱高效并发的第一课

当多个线程同时操作同一个队列时,你是否遇到过这些问题:

  • 队列在高并发时突然变慢
  • 线程被锁阻塞导致CPU空闲
  • 程序难以利用多核处理器的全部性能

这就是无锁队列要解决的核心问题!今天我们就用最平实的方式理解这个强大的并发工具。

一、为什么需要无锁队列?

传统锁队列的痛点

std::queue<T> q;
std::mutex mtx;void enqueue(T item) {std::lock_guard lock(mtx); // 锁定q.push(item);// 解锁自动发生
}

这种实现在高并发时会遇到:

  • 锁竞争:线程排队等待锁释放
  • 上下文切换:CPU切换线程开销大
  • 优先级反转:高优先级线程被低优先级线程阻塞

无锁队列的优势

无锁队列使用原子操作替代传统锁:

  • ⚡ 线程永不阻塞
  • 🚀 极低延迟操作
  • 🎛️ 完美利用多核CPU

二、核心武器:CAS原子操作

Compare-And-Swap (比较并交换)

bool atomic_compare_exchange(atomic<T>* obj, T* expected, T desired);

这条指令保证三步操作原子性

  1. 检查当前值是否等于expected
  2. 如果相等,设置为desired
  3. 返回操作是否成功

CAS就像邮局的"取件码"系统:

  1. 报号码(expected)
  2. 验证是你的包裹
  3. 取走包裹(更新为desired)

C++中的CAS

std::atomic<int> value = 0;
int expected = 0;// 尝试将0改成1
bool success = value.compare_exchange_strong(expected, 1);

三、简单实现:单生产者单消费者(SPSC)

队列结构

Dummy
数据1
数据2
NULL

代码实现(带详细注释)

#include <atomic>template<typename T>
class SimpleLockFreeQueue {
private:struct Node {T data;std::atomic<Node*> next;};std::atomic<Node*> head; // 头指针std::atomic<Node*> tail; // 尾指针public:SimpleLockFreeQueue() {// 创建虚拟节点作为初始节点Node* dummy = new Node();head.store(dummy); // 头指向虚拟节点tail.store(dummy); // 尾也指向虚拟节点}// 生产者线程使用void push(const T& value) {// 创建新节点Node* newNode = new Node{value, nullptr};Node* currentTail = tail.load(); // 获取当前尾指针// 尝试更新尾节点的next指针while(!currentTail->next.compare_exchange_weak(nullptr,    // 预期值:应该是空指针newNode))   // 目标值:设置为新节点{// CAS失败:说明其他线程已经修改,刷新尾指针currentTail = tail.load();}// 移动尾指针到新节点tail.compare_exchange_weak(currentTail, newNode);}// 消费者线程使用bool pop(T& result) {Node* currentHead = head.load(); // 当前头节点Node* nextNode = currentHead->next.load(); // 头节点的下个节点if(nextNode == nullptr) {return false; // 队列为空}// 取出数据result = nextNode->data;// 移动头指针head.store(nextNode);// 删除旧头节点(安全处理内存)delete currentHead;return true;}
};

四、无锁队列的演进路线

从简单到复杂

  1. SPSC(单生产者单消费者)

    • 一个生产者 + 一个消费者
    • 最简单的无锁模型
  2. MPSC(多生产者单消费者)

    • 多个生产者 + 一个消费者
    • 需要处理多个生产者的竞争
  3. MPMC(多生产者多消费者)

    • 多个生产者 + 多个消费者
    • 需要处理ABA问题(进阶话题)

五、实战技巧与注意事项

何时使用无锁队列?

场景建议方案
低并发(<1k操作/秒)互斥锁队列
中等并发(1k-100k操作/秒)无锁SPSC队列
高并发(>100k操作/秒)专业无锁队列库

内存安全提示

无锁队列最大的陷阱:

delete currentHead; // 如果其他线程还在访问?

解决方案:

  1. 使用智能指针(shared_ptr)管理内存
  2. 实现安全期(Grace Period)机制
  3. 使用专业库(Boost.lockfree)的内存管理

初学者建议

  1. 优先实现SPSC队列
  2. 使用std::memory_order_relaxed简化:
    tail.compare_exchange_weak(currentTail, newNode,std::memory_order_relaxed, std::memory_order_relaxed);
    
  3. 使用线程分析工具(Valgrind, ThreadSanitizer)

六、快速开始指南

  1. 在代码中实现SPSC队列类
  2. 创建生产者线程:
    void producer(SimpleLockFreeQueue<int>& q) {for(int i = 0; i < 1000; i++) {q.push(i);}
    }
    
  3. 创建消费者线程:
    void consumer(SimpleLockFreeQueue<int>& q) {int value;while(true) {if(q.pop(value)) {process(value); // 处理数据}}
    }
    
  4. 启动线程:
    SimpleLockFreeQueue<int> q;
    std::thread p(producer, std::ref(q));
    std::thread c(consumer, std::ref(q));
    

结语:开启高效并发之门

无锁队列将彻底改变你处理多线程编程的方式。虽然它比传统队列更复杂,但带来的性能提升是革命性的!

下一步学习:

  1. 尝试添加多生产者支持
  2. 研究Boost.lockfree源码
  3. 探索无锁内存回收机制
  4. 了解ABA问题与解决方案

“如果你能理解无锁队列,就能理解现代高性能系统的核心秘密。” - 来自某位匿名系统架构师

无锁编程是通向高级系统开发的必经之路,从这里开始你的高效并发之旅吧!


推荐:C++学习一站式分享

http://www.lqws.cn/news/515323.html

相关文章:

  • Sivers毫米波产品系列全景图:覆盖通信、工业、交通、航天
  • Xcode缓存清除
  • 鸿蒙Next仓颉开发语言中的数据类型总结分享
  • java 导出word 实现循环表格
  • 配置有nvlink的H20使用pytorch报错
  • 在树莓派上用 .NET8.0 挂载TCP服务端
  • React ref 和 JS 对象的区别
  • Linux系统之Tomcat服务
  • django csrf的局限性
  • 亚远景-ASPICE与ISO 26262:汽车安全与软件质量的协同
  • 云原生灰度方案对比:服务网格灰度(Istio ) 与 K8s Ingress 灰度(Nginx Ingress )
  • 【Pandas】pandas DataFrame asfreq
  • stm32week17+18+19+20
  • IP-GUARD外设以及网络禁用策略制定
  • ubuntu22.04可以执行sudo命令,但不在sudo组
  • 学习日记-spring-day37-6.25
  • NETCONF 典型工作流程
  • Spark 之 UT
  • 新能源汽车电池类型差异分析
  • 网络安全漏洞扫描是什么?如何识别目标进行扫描?
  • LangGraph--基础学习(Subgraphs 子图)
  • easy-caffeine一个简洁灵活易用基于caffeine的本地缓存框架
  • dovi交叉编译方法(编译libdovi.so)
  • PyTorch 入门之官方文档学习笔记(二)训练分类器
  • 利用Pytorch玩一玩文生图的HDGAN
  • 长尾关键词SEO优化高效策略
  • 微信小程序安卓手机输入框文字飘出输入框
  • 【服务器】服务器选型设计
  • Hadoop之HDFS
  • 【iOS】iOS崩溃总结