gpt4 book ai didi

C++11如何实现无锁队列

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 40 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章C++11如何实现无锁队列由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

atomic 。

compare_exchange_weak / compare_exchange_strong 当前值与期望值相等时,修改当前值为设定值,返回true 当前值与期望值不等时,将期望值修改为当前值,返回false 。

memory_order枚举值 。

C++11如何实现无锁队列

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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。

示例代码如下:

?
1
2
3
4
5
6
7
8
9
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问题

所谓ABA(见维基百科的ABA词条),问题基本是这个样子:

  • 进程P1在共享变量中读到值为A
  • P1被抢占了,进程P2执行
  • P2把共享变量里的值从A改成了B,再改回到A,此时被P1抢占。
  • P1回来看到共享变量里的值没有被改变,于是继续执行。

虽然P1以为变量值没有改变,继续执行了,但是这个会引发一些潜在的问题。ABA问题最容易发生在lock free 的算法中的,CAS首当其冲,因为CAS判断的是指针的地址。如果这个地址被重用了呢,问题就很大了。(地址被重用是很经常发生的,一个内存分配后释放了,再分配,很有可能还是原来的地址) 。

eg: 好比你拿着一个装满钱的手提箱在飞机场,此时过来了一个火辣性感的美女,然后她很暖昧地挑逗着你,并趁你不注意的时候,把用一个一模一样的手提箱和你那装满钱的箱子调了个包,然后就离开了,你看到你的手提箱还在那,于是就提着手提箱去赶飞机去了.

这就是ABA的问题.

Fetch-And-Add (FAA) 。

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

Test-And-Set (TAS) 。

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

参考文章 。

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

到此这篇关于C++11如何实现无锁队列的文章就介绍到这了,更多相关C++11无锁队列内容请搜索我以前的文章或继续浏览下面的相关文章希望大家以后多多支持我! 。

原文链接:https://blog.csdn.net/u010275850/article/details/118468234 。

最后此篇关于C++11如何实现无锁队列的文章就讲到这里了,如果你想了解更多关于C++11如何实现无锁队列的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

40 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com