我担心嵌套的指针和访问,特别是在处理基于无锁节点的树结构时是否有避免这种ABA问题的方法。
我的关注如下:
标准是否对此做出保证,funcB是否等同于funcA?
如果这里存在ABA问题,那么是否有解决嵌套成员访问的无锁编程解决方案?
#include <atomic>
#include <iostream>
struct Foo
{
std::atomic_int value;
};
struct Bar
{
Foo * foo;
};
void funcB(Bar * bar)
{
if (not bar->foo->value.fetch_or(1) )
{
//Something
}
}
void funcA(std::atomic_int * bar)
{
if (not bar->fetch_or(0))
{
//Something
}
}
上面的程序集输出为:
funcB(Bar*): # @funcB(Bar*)
mov rax, qword ptr [rdi]
lock or dword ptr [rax], 1
ret
funcA(Foo*): # @funcA(Foo*)
lock or dword ptr [rdi], 1
ret
答案 0 :(得分:1)
您的示例并未真正显示出ABA问题。 Wikipedia:
[..]同步期间发生ABA问题,当两次读取一个位置,两次读取具有相同的值,并且“值相同”用于表示“没有任何变化”。但是,另一个线程可以在两次读取之间执行并更改值,执行其他工作,然后将值改回,因此,即使第二个线程的工作违反了该假设,也使第一个线程认为“什么都没有改变”。
也就是说,在指针被取消引用时,确保指针仍然有效(即,指向尚未释放的现有对象/内存)是您的责任。如果涉及多个线程,则您的职责是确保避免潜在的数据争夺所需的必要的先发生后关系(如果有)。
在无锁算法中避免ABA问题可能非常棘手。通常,将其委托给已建立的内存回收方案最简单。我的xenium库提供了可用于此目的的各种回收方案的实现。