C++11 C++;11无锁堆栈 我在Anthony Williams的操作中读取C++并发,不理解它的代码

C++11 C++;11无锁堆栈 我在Anthony Williams的操作中读取C++并发,不理解它的代码,c++11,stack,lock-free,C++11,Stack,Lock Free,究竟为什么原子加载不在while循环中?他给出的理由是: 因此,您不必每次通过循环时都重新加载磁头, 因为编译器是为你做的 但我不明白。有人能解释一下吗 template<typename T> class lock_free_stack { private: struct node { T data; node* next; node(T const& data_) : data(data_) {} }; std::atomic&

究竟为什么原子
加载
不在while循环中?他给出的理由是:

因此,您不必每次通过循环时都重新加载磁头, 因为编译器是为你做的

但我不明白。有人能解释一下吗

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(); 
   while(!head.compare_exchange_weak(new_node->next,new_node)); 
 }
};
模板
类锁\u自由\u堆栈
{
私人:
结构节点
{
T数据;
节点*下一步;
节点(T常数和数据):
数据(数据)
{}
};
原子头;
公众:
无效推送(T常量和数据)
{
node*const new_node=新节点(数据);
新建节点->下一步=head.load();
而(!head.compare_exchange_弱(新建节点->下一步,新建节点));
}
};

键位于接口中,在本例中,该接口包含两个参数。第一个是对期望值的引用,第二个是期望值。如果原子的当前值不等于预期输入,它将返回false,并且预期输入设置为当前值


所以在本例中,它所做的是设置
new\u node->next=head
。然后,如果
head
仍然等于
new\u node->next
,则将其交换为
head
。如果它不再是该值,它将使用对
new\u node->next
的引用来为其分配
head
的当前值。由于循环的每次迭代失败后,都会将
new\u node->next
替换为
head
的当前值,因此在循环体中没有复制该值的读取操作。

来自
compare\u exchange\u-weak
的文档:

以原子方式将*中存储的值与的值进行比较 预期的,如果两者相等,则将前者替换为预期的 (执行读修改写操作)。否则,将加载实际的 将*中存储的值转换为预期值(执行加载操作)


如您所见,否则,
head
的实际值将加载到expected中。

是的,它现在非常合理。谢谢