As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center提供指导。




7年前关闭。




我正在寻找一些在多线程代码中引起麻烦的ABA问题的真实示例。

执行原子比较和交换指令时,并发代码中会发生ABA问题。如果一个线程在执行比较和交换之前立即被中断,则另一个线程可能会将比较和交换的目标从其初始值A更改为另一个值B。如果随后将其值更改回A在第一个线程恢复之前,尽管目标值已更改,但比较和交换操作仍将成功。

在许多情况下,ABA不是问题。以一个共享的引用计数为例:即使同时更改了引用计数,只要我们从未从已经下降到0的引用计数增加就没有问题。因此,我们显然只对目标是否匹配目标计数感兴趣。交换时的期望值,而不是过去是否已更改。

wikipedia page有一个受ABA影响的无锁堆栈实现的示例,但是到目前为止,我个人还没有在生产代码中遇到问题。我很好奇,是否有人可以分享一些关于ABA的精彩 war 故事。

最佳答案

假设您要使用传统的链表实现有序列表。假设您要向列表中添加一个新值V。首先,您必须找到正确的位置以使用辅助指针AUX插入新元素,并将其放置在最后一个小于V的节点中,并保存AUX-> next以在CAS操作中进行比较。获得引用后,将NEW-> next指向AUX-> next,然后使用CAS如果AUX-> next与您保存的引用相同,则将AUX-> next切换为NEW。应该是这样的:

AUX = list.HEAD;
WHILE( AUX->next.value < V)
    AUX = AUX->next;
OLD = AUX->next; //line 4
NEW->next = AUX->next; //line 5
IF( CAS(AUX->next, NEW, OLD)) //line 6
    Success!!!
ELSE
    Try again or whatever

这是最简单的方法。问题是在第4行和第5行之间,另一个线程可能已删除“OLD”,然后插入了另一个小于V但仍大于AUX.value的元素X。如果发生这种情况,并且分配给值X的节点的内存与以前使用OLD的地址相同,则CAS将成功,但是列表将不排序。如果第二个线程的 Action 发生在第5行和第6行之间,则将丢失值为X的节点。所有这些都是由于ABA问题。

关于multithreading - ABA在多线程中的实际示例,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14535948/

10-10 01:12