为什么您可以从lock_free_stack中的pop()中的Atomic Compare_exchange_weak中取出的节点免费?
我正在阅读《行动》第二本书的< c ++并发。 ed>由安东尼·威廉姆斯(Anthony Williams) 第7.2.2节停止了那些讨厌的泄漏:在无锁数据中管理内存。
在本节之前,我们
template <typename T> class lock_free_stack {
private:
struct node {
std::shared_ptr<T> data;
node *next;
node(T const &data_) : data(std::make_shared<T>(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));
}
std::shared_ptr<T> pop() {
node *old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next));
return old_head ? old_head->data : std::shared_ptr<T>();
}
};
在第7.2.2节中实施了一个lock_free_stack,安东尼说:
当您第一次查看pop()时,您选择泄漏节点以避免比赛 一个线程删除节点的条件,而另一个线程仍然容纳指针 对此即将退出。
我不了解,如果两个线程同时调用pop(),则每个线程都会有不同的头,因此每个线程的old_head彼此不同,并且它们可以自由删除old_head。
我认为,无内存的裂变流行音乐()是:
std::shared_ptr<T> pop() {
node *old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next));
std::shared_ptr<T> res = old_head ? old_head->data : std::shared_ptr<T>();
delete old_head;
return res;
}
如何理解安东尼的话?
I'm reading the book <c++ concurrency in action 2nd. Ed> by Anthony Williams
Section 7.2.2 Stopping those pesky leaks: managing memory in lock-free data strcutures.
before this section, we implemented a lock_free_stack
template <typename T> class lock_free_stack {
private:
struct node {
std::shared_ptr<T> data;
node *next;
node(T const &data_) : data(std::make_shared<T>(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));
}
std::shared_ptr<T> pop() {
node *old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next));
return old_head ? old_head->data : std::shared_ptr<T>();
}
};
in section 7.2.2, anthony said:
When you first looked at pop(), you opted to leak nodes in order to avoid the race
condition where one thread deletes a node while another thread still holds a pointer
to it that it’s about to dereference.
I don't understand, if two threads calling pop() concurrently, each thread will get different head, so old_head of each thread differes from each other, and they are free to delete old_head.
In my opinion, the no-memory-leaks pop() would be:
std::shared_ptr<T> pop() {
node *old_head = head.load();
while (old_head && !head.compare_exchange_weak(old_head, old_head->next));
std::shared_ptr<T> res = old_head ? old_head->data : std::shared_ptr<T>();
delete old_head;
return res;
}
How to understand what anthony says ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
比赛在这里
可能的一场比赛是:
old_head-&gt; next
,在其自己的调用之前,已删除了compare_exchange_weak_weak
The race is here
One possible race is:
old_head->next
, which has been deleted, just prior to its own call tocompare_exchange_weak
让我们假设2个线程Enter
pop
同时却被中断了,因此中断了这样的中断:两个线程都以相同的
old_head = head.load();
开始。然后线程1删除对象,然后在该线程2访问old_head--&gt; Next
。这是免费的。Lets assume 2 threads enter
pop
at the same time but thread 2 gets interrupted for a bit like this:Both threads start with the same
old_head = head.load();
. Then thread 1 deletes the object and after that thread 2 accessesold_head->next
. That's access after free.