- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
在书中C++ Concurrency in Action ,作者给出了一个使用hazard pointer实现无锁栈数据结构的例子。部分代码如下:
std::shared_ptr<T> pop()
{
std::atomic<void*>& hp=get_hazard_pointer_for_current_thread();
node* old_head=head.load();
node* temp;
do
{
temp=old_head;
hp.store(old_head);
old_head=head.load();
} while(old_head!=temp);
// ...
}
描述是这样说的
You have to do this in a
while
loop to ensure that thenode
hasn’t been deleted between the reading of the oldhead
pointer and the setting of the hazard pointer. During this window no other thread knows you’re accessing this particular node. Fortunately, if the oldhead
node is going to be deleted,head
itself must have changed, so you can check this and keep looping until you know that thehead
pointer still has the same value you set your hazard pointer to.
我认为代码有缺陷,因为 head
节点受制于 ABA problem .即使head
的值保持不变,它原来指向的节点也可能已经被删除了。分配了一个新的head
节点,它恰好与前一个节点具有相同的地址值。
最佳答案
默认memory_order
load()
操作是 std::memory_order_seq_cst
,它确保所有操作的顺序一致性(总体全局排序):
Each
memory_order_seq_cst
operationB
that loads from atomic variableM
, observes one of the following:
- the result of the last operation
A
that modifiedM
, which appears beforeB
in the single total order- OR, if there was such an
A
,B
may observe the result of some modification onM
that is notmemory_order_seq_cst
and does not happen-beforeA
- OR, if there wasn't such an
A
,B
may observe the result of some unrelated modification ofM
that is notmemory_order_seq_cst
.
因此,如果节点被修改(删除)并且这发生在第二次读取全局总顺序之前,您一定会看到该更改,因此循环将继续执行。如果此修改在之后进行,则不会有任何危害,因为已经设置了风险指针。
你有这个保证,因为存储到危险指针也是用 std::memory_order_seq_cst
完成的。此内存顺序为加载提供了一个获取操作,为存储提供了一个释放操作,从而防止在同一线程内重新排序。因此,“成功”读取 (old_head==temp
) 保证保存了正确的数据。
将这两个负载视为同步点 - 因为它们执行 acquire 操作,所以它们与修改这些值的相应 release 操作同步,导致所有写入成为可见。
您描述的问题在任何方面都不会影响示例。 pop()
函数用于删除顶部元素,它会执行此操作。如果在此期间添加/删除元素,它将弹出它,无论它的地址是什么(它甚至可能与之前获取的地址相同)。这是一个完全不同的问题。考虑:
concurrent_stack<int> p;
if (!p.empty() && (p.top() == 5))
{
auto t = p.pop();
assert( t ); // May fail
assert( *t == 5 ); // May fail
}
这两个断言都可能失败,如果许多线程非常密集地使用堆栈,很可能会经常失败。但这不是由于 pop()
的错误实现,而是您需要更强的访问限制以确保确实从堆栈中删除最后检查的元素。
关于c++ - 这个危险指针示例是否因为 ABA 问题而存在缺陷?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48783613/
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一年级的学生,目前正在学习“C”。这是我真正碰壁的第一个任务,任务是: “创建一个函数,它接收一个字符串指针和一个字符串大小的指针。字符串本身包含一个句子。该函数将返回一个指向最大字典大小单词开头
我必须运行一个相当旧的程序代码,它使用 ABA-provider for JCE。所有类都可以在源文件夹中找到。但是,会出现 NoSuchProviderException:“JCE 无法验证提供程序
我正在尝试从 here 实现 Michael-Scott FIFO 队列。我无法实现他们针对 ABA 问题的解决方案。我收到此错误。 error: incompatible type for argu
我目前正在使用 C++11 开发无锁单链表,我的 popFront() 函数有问题——或者我至少应该说我知道它在某些情况下会出现问题。 无论如何,这就是我目前拥有的: std::shared_ptr
在书中C++ Concurrency in Action ,作者给出了一个使用hazard pointer实现无锁栈数据结构的例子。部分代码如下: std::shared_ptr pop() {
我在维基百科的实践书中调查了并发中的 ABA 问题,我阅读了以下内容 post 据我所知,ABA 问题的根本原因是在算法中我们检查的状态与以前相同,但算法暗示状态未被触及。 堆栈数据结构示例: 我们使
我读了一篇描述 ABA 问题的文章,但有些东西我无法理解。我有源代码,它无法运行,它类似于文章中的示例,但我不明白这个问题。这是文章 http://fara.cs.uni-potsdam.de/~js
在给定两个字符的出现频率(例如:x = 5)的情况下,建议一种使用两个字符(例如:“aabba”、“aba”)的模式构造 String 的有效方法, y = 4).问题是任何字符都不应重复超过两次。
请注意,我已经知道并了解 ABA problem .这个问题是关于 .NET 内存模型在 ABA 方面的行为。 在他对 Lock-Free LIFO Stack 的讨论中(2007 年 5 月 MSD
从 AIM 7 beta 2 到现在的 AIM 7 beta 6,GM - AIM 开始使用新的 .aba 文件格式来保存文件。这些文件过去位于我们可以访问的文件夹中程序文件,但是由于“性能提升”,A
我正在阅读 lock free boost 文档的一部分,它说“使用固定大小的数组来存储内部节点”以避免在 32 位机器上防止 ABA 问题。有人可以给我提示这部分在源代码中的位置吗?整个 boost
我有一种情况需要更新候选人的选票。 公民可以投票给这个候选人,每个候选人可以投一票以上。即一个人可以投 5 票,而另一个人可以投 2 票。在这种情况下,该候选人应获得 7 票。 现在,我使用 Djan
我正在基于此实现一个无锁队列 algorithm ,它使用计数器来解决 ABA 问题。但我不知道如何用 c++11 CAS 实现这个计数器。例如,从算法: E9: if CAS(&tail.pt
我正在尝试对字符串进行排序(为 punnetsquare 制作基因型)。我当前的实现是: unsorted_genotype = 'ABaB' sorted_genotype = sorted(lis
我需要运行一个服务程序,用 FO 为 abas-ERP continuous 编写。 我听说一些已经存在的脚本可以从 shell 调用服务程序。如果可能的话,我可以简单地使用一个 cronjob 来启
当使用比较和交换 (CAS) 技术编写无锁代码时,存在称为 ABA 问题的问题: http://en.wikipedia.org/wiki/ABA_problem 因此,仅比较值“A”是有问题的,因为
我想知道为什么下面的函数会出错: #include using namespace std; class Saba { public: Saba(){ cout (sabaPtr);
在一些论坛和书籍中(即 C++ Concurrency in Action)有一个很好的多生产者/多消费者堆栈的例子,并且在 pop 实现中他们通常这样做以下内容: // head is an std
是否有任何 FO 函数或 AJO 函数来获取在屏幕编辑器中声明的必填字段? 最佳答案 据我所知FO中没有这个功能。前段时间我自己需要这些信息,我从 xml 屏幕描述文件中获取了这些信息。 必填字段看起
我是一名优秀的程序员,十分优秀!