我正在阅读安东尼·威廉姆斯的“在行动中的C++并发”,并且不理解它的lock_free_stack类的push实现。
为什么原子load不在Why循环中?他说的原因是:
因此,您不必每次通过循环重新加载head,因为编译器为您做了这些工作。
但我不明白。有人能解释一下这件事吗?
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));
}
};发布于 2014-06-30 16:03:48
键位于compare_exchange_weak的接口中,在本例中,该接口包含2个参数。第一个是对期望值的引用,第二个是对期望值的引用。如果原子的当前值不等于预期的输入,它将返回false,并将预期的输入设置为当前值。
所以在这种情况下,它所做的就是设置new_node->next = head。然后,如果head仍然等于new_node->next,则将其转换为head。如果它不再是该值,它将使用对new_node->next的引用来为它分配head的当前值。因为失败的循环的每一次迭代都用当前的new_node->next值head替换了head,所以在循环的正文中没有重复的读取。
发布于 2014-06-30 16:04:33
来自compare_exchange_weak的文档
原子地将存储在*中的值与预期值进行比较,如果它们相等,则用所需的值替换前者(执行读-修改-写入操作)。否则,将存储在*中的实际值加载到预期中(执行加载操作)。
正如您所看到的,否则head的实际值将加载到预期中。
https://stackoverflow.com/questions/24493829
复制相似问题