首页 > 运维 > linux运维 > 正文

C++并发实战19:lock free编程

雪夜
发布: 2025-07-20 08:42:02
原创
786人浏览过

大家好,又见面了,我是你们的朋友全栈君。涉及到并行/并发计算时,通常都会想到使用锁来保护共享的数据,但锁的使用也存在一些问题:

  1. 效率降低:由于临界区无法并发运行,进入临界区需要等待,锁的使用导致效率下降。多核CPU也无法充分发挥其性能。
  2. 死锁风险:在复杂的情况下,很容易造成死锁,导致并发进程或线程之间无止境地互相等待。
  3. 中断/信号处理函数中的限制:在中断或信号处理函数中不能使用锁,这给并发处理带来了困难。
  4. 影响实时性:锁会影响实时性,等待时间不确定。
  5. 优先级反转:高优先级的线程可能需要等待低优先级的线程。
  6. 线程挂起问题:如果一个线程在持有锁的情况下挂起,会影响其他等待该锁的线程。

总之,在基于锁的多线程/多进程编程中,你需要确保对竞争条件敏感的共享数据上的任何操作,都通过加锁或解锁一个互斥锁(mutex)来实现原子操作。

现有的加锁和无锁编程的种类如下:

C++并发实战19:lock free编程

其中,标注为红色字体的方案为Blocking synchronization(需要锁),黑色字体的为Non-blocking synchronization(无锁)。Lock-based和Lockless-based两者之间的区别仅仅是加锁粒度的不同。图中最底层的方案就是大家经常使用的mutex和semaphore等方案,代码复杂度低,但运行效率也最低。

立即进入豆包AI人工智官网入口”;

立即学习豆包AI人工智能在线问答入口”;

豆包AI编程
豆包AI编程

豆包推出的AI编程助手

豆包AI编程483
查看详情 豆包AI编程

可以使用std::atomic来实现lock free编程,但这里并不是真正的无锁,只有atomic_flag是无锁的,其他atomic内部都是有锁的,只不过粒度很小。atomic::compare_exchange_weak/strong等同于CAS(比较并交换)操作,在C++11之前该操作是平台相关的,现在atomic将其实现为成员函数。

下面是一个lock free的栈的示例:

#include <atomic>
#include <memory>
<p>template<typename T>
class lock_free_stack // 栈的底层数据结构采用单向链表实现
{
private:
struct node
{
std::shared_ptr<T> data; // 这里采用shared<em>ptr管理的好处在于:若栈内存放对象,pop中return栈顶对象可能拷贝异常,栈内只存储指针还可以提高性能
node* next;
node(T const& data</em>) : data(std::make<em>shared<T>(data</em>)) // 注意make_shared比直接shared_ptr构造的内存开销小
{}
};
std::atomic<node*> head; // 采用原子类型管理栈顶元素,主要利用atomic::compare_exchange_weak实现lock free</p><p>public:
void push(T const& data)
{
node* const new_node = new node(data);
new_node->next = head.load(); // 每次从链表头插入
while (!head.compare_exchange_weak(new_node->next, new_node)); // 若head==new_node->next则更新head为new_node,返回true结束循环,插入成功;若head!=new_node->next表明有其它线程在此期间对head操作了,将new_node->next更新为新的head,返回false,继续进入下一次while循环。这里采用atomic::compare_exchange_weak比atomic::compare_exchange_strong快,因为compare_exchange_weak可能在元素相等的时候返回false所以适合在循环中,而atomic::compare_exchange_strong保证了比较的正确性,不适合用于循环
}</p><pre class="brush:php;toolbar:false;"><code>std::shared_ptr<T> pop()
{
    node* old_head = head.load(); // 拿住栈顶元素,但是可能后续被更新,更新发生在head!=old_head时
    while (old_head && !head.compare_exchange_weak(old_head, old_head->next)); // 这里注意首先要先判断old_head是否为nullptr防止操作空链表,然后按照compare_exchange_weak语义更新链表头结点。若head==old_head则更新head为old_head->next并返回true,结束循环,删除栈顶元素成功;若head!=old_head表明在此期间有其它线程操作了head,因此更新old_head为新的head,返回false进入下一轮循环,直至删除成功。
    return old_head ? old_head->data : std::shared_ptr<T>(); // 这里注意空链表时返回的是一个空的shared_ptr对象
} // 这里只是lock free,由于while循环可能无限期循环不能在有限步骤内完成,故不是wait free
登录后复制

};

发布者:全栈程序员栈长,转载请注明出处:https://www.php.cn/link/46c6a6c72edf42b1335217a9eb4b2325 原文链接:https://www.php.cn/link/c8377ad2a50fb65de28b11cfc628d75c

以上就是C++并发实战19:lock free编程的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号