无锁操作的本质依赖的原子操作,C++11提供了atomic的原子操作支持

  • atomic
  • compare_exchange_weak / compare_exchange_strong
    当前值与期望值相等时,修改当前值为设定值,返回true
    当前值与期望值不等时,将期望值修改为当前值,返回false
  • memory_order枚举值
template<typename T>
class lock_free_stack
{
private:struct node{T data;node* next;node(T const& data_):data(data_){}};std::atomic<node*> head;public:void push(T const& data){node* const new_node=new node(data);new_node->next=head.load();  /*** 当前值.compare_exchange_weak(期望值, 设置值)** 单线程的情况:** 第一次执行while循环:** 此时当前值与期望值相等,修改当前值为设定值 head = new_node,返回true** 多线程的情况:** 第一次执行循环体的时候:** compare_exchange_weak如果失败, 返回false, 证明有其他线程更新了栈顶head,** 当前值与期望值不等时,将期望值修改为当前值, 即new_node->next等于新的栈顶head,** 被其他线程更新的新栈顶值会被更新到new_node->next中,** 因此循环可以直接再次尝试压栈而无需由程序员更新new_node->next。** 然后第二次执行循环体:** 此时 head == new_node->next, 所以 head = new_node.** 如果这是仍有其他线程干扰,则仍为循环更新new_node->next*/while(!head.compare_exchange_weak(new_node->next,new_node));}
};

CAS原子操作

  • CAS即Compare and Swap,是所有CPU指令都支持CAS的原子操作(X86中CMPXCHG汇编指令),用于实现实现各种无锁(lock free)数据结构。
  • CAS用于检查一个内存位置是否包含预期值,如果包含,则把新值复赋值到内存位置。成功返回true,失败返回false。示例代码如下:
    bool compare_and_swap ( int *memory_location, int expected_value, int new_value)
    {if (*memory_location == expected_value){*memory_location = new_value;return true;}return false;
    }
    

ABA问题

假设有两个线程——线程1和线程2,两个线程按照顺序进行以下操作:

  1. 线程1读取内存中数据为A;
  2. 线程2将该数据修改为B;
  3. 线程2将该数据修改为A;
  4. 线程1对数据进行CAS操作

在第4步中,由于内存中数据仍然为A,因此CAS操作成功,但实际上该数据已经被线程2修改过了,可能存在潜藏的问题,例如栈顶问题:一个栈的栈顶经过两次(或多次)变化又恢复了原值,但是栈可能已发生了变化。这就是ABA问题。

解决思路
对于ABA问题,比较有效的方案是引入版本号,内存中的值每发生一次变化,版本号都+1;在进行CAS操作时,不仅比较内存中的值,也会比较版本号,只有当二者都没有变化时,CAS才能执行成功。Java中的AtomicStampedReference类便是使用版本号来解决ABA问题的。

Fetch-And-Add (FAA)

一般用来对变量做+1的原子操作

Test-And-Set (TAS)

写值到某个内存位置并传回其旧值

参考文章

C++11:原子交换函数compare_exchange_weak和compare_exchange_strong

C++11 - 无锁队列相关推荐

  1. 你应该知道的高性能无锁队列Disruptor

    1.何为队列 听到队列相信大家对其并不陌生,在我们现实生活中队列随处可见,去超市结账,你会看见大家都会一排排的站得好好的,等待结账,为什么要站得一排排的,你想象一下大家都没有素质,一窝蜂的上去结账,不 ...

  2. 基于数组的无锁队列(译)

    2019独角兽企业重金招聘Python工程师标准>>> 1 引言 最近对于注重性能的应用程序,我们有了一种能显著提高程序性能的选择:多线程.线程的概念实际上已经存在了很长时间.在过去 ...

  3. CAS操作与无锁队列

    在多线程编程中,为了保证内存的可见性,我们加入了一些锁的机制,例如信号量,互斥锁,条件变量等等,但是锁的机制不是一个简单的机制,需要加入很多的控制,所以在使用中又有了一些轻量级的同步机制,例如vola ...

  4. linux 无锁队列覆盖问题,无锁队列杂谈

    质量最大vczh粉(402740419) 10:13:17 nobody(1575393351)  10:10:09 无锁队列,怎么可能 ? 质量最大vczh粉(402740419) 10:13:23 ...

  5. 实用的无锁队列(一)

    写一个无锁队列的好处 针对应用场景写无锁队列好处是能够得到额外的cpu释放 1. atomic_thread_fence C++11的原子库标准定义了一个可移植的函数atomic_thread_fen ...

  6. 无锁队列以及ABA问题

    队列是我们非常常用的数据结构,用来提供数据的写入和读取功能,而且通常在不同线程之间作为数据通信的桥梁.不过在将无锁队列的算法之前,需要先了解一下CAS(compare and swap)的原理.由于多 ...

  7. 无锁队列的实现 | 酷壳 - CoolShell.cn

    无锁队列的实现 | 酷壳 - CoolShell.cn 无锁队列的实现 | 酷壳 - CoolShell.cn 无锁队列的实现 posted on 2013-01-14 11:30 lexus 阅读( ...

  8. CAS无锁队列的实现

    文章目录 1. 基本原理 2. 代码实现 2.1 使用链表实现无锁队列 2.2 使用数组实现环形无锁队列 3. ABA 问题及解决 4. 参考资料 1. 基本原理 源于1994年10月发表在国际并行与 ...

  9. [数据结构]——无锁队列

    (152条消息) [数据结构]--无锁队列_lucky52529的博客-CSDN博客_无锁队列无锁队列 写这篇博客前想声名以下几点.第一,这篇文章重点内容是关于无锁队列如何实现,并不会深入讲解底层的C ...

最新文章

  1. XtraGrid GridView设置默认选中的行颜色
  2. python获取已打开网页的html,【已解决】Python的BeautifulSoup去实现提取带tag的HTML网页主体内容...
  3. java 常量池详解
  4. MyBaits 支持哪些数据源类型?
  5. matlab2012生成dll,64位win7下vc2010如何調用matlab2012a中生成的dll文件
  6. Win10 UAP 绑定
  7. TDengine和DolphinDB哪个更好,哈哈哈哈,闲来无聊分析了一下。
  8. 从SVN迁移到Git(包括SVN历史纪录)【最系统的讲解】
  9. 几何常用算法与判断线段相交【转】
  10. 【软件领域知识整理】贵金属交易的K线图解释(二)
  11. 作为一名大厂的测试人员,软件测试真的是一份低调的工作吗?
  12. node.js(五)项目创建管理
  13. Google两步验证的工作原理
  14. FZU《C语言程序综合设计》
  15. 每个极客都应该知道的Linux技巧(区分开普通的Linux用户和超级极客)
  16. 无线通信设备安装工程概预算编制_深圳电气安装造价培训-如何计算电气设备安装工程预算定额?...
  17. JavaScript格式化时间与日期
  18. linux服务器共享网络设置方法,Windows和linux网络共享 配置网上邻居
  19. 两向量叉乘的计算公式_向量的数量积和向量积怎么算?
  20. 微信公众号开发之(35)地图导航

热门文章

  1. 借助开源项目,学习软件开发——开始
  2. 程序员写小工具方便老婆工作,离职时老板:人走,工具留下
  3. 相机模型之鱼眼模型(Equidistant)
  4. linux(凝思系统)进入单用户模式
  5. 中芯国际连发两份重要公告;电子元器件迎重磅政策支持;诺基亚全年手机出货量仅4660;亚信中标上海联通5G消息运营平台...
  6. 2022.4.30—2022.6.22 学习报告
  7. Java类的实践:使用Java类描述一个车类
  8. 网页播放flash无声音解决方案
  9. org.apache.ibatis.binding.BindingException: Invalid bound statement(not found):
  10. 服务器 网站 维护,网站服务器如何做好日常维护?