关于内存屏障的使用,我有一些不明白的地方,我希望得到澄清。
所以,假设我们有一个 Treibers 堆栈,但是我们使用的是 SMR,所以没有与每个指针关联的计数器 - 我们必须在我们的原子操作中正确获取指针(这与 ABA 无关 - 我们使用的是 SMR,处理 ABA,这不是问题的一部分)。
现在,假设我们正在使用 Intel (x86/x64),因此每个 CAS 都带有完整的内存屏障。我认为CASing 时会发生什么情况是缓存行被锁定,发出读屏障,这会清除无效队列,缓存行因此加载该缓存行的最新版本,发生比较,然后写屏障是发出,刷新存储缓冲区,最后我们释放缓存行锁。
所以,我们有下面的pop代码;
BARRIER_PROCESSOR_READ;
original_top = stack_state->top;
do
{
if( original_top == NULL )
return( 0 );
copy_of_original_top = original_top;
original_top = compare_and_swap( &stack_state->top, original_top->next, original_top );
}
while( copy_of_original_top != original_top );
*user_data = original_top->user_data;
所以,我们首先发出一个读屏障——这确保我们刷新我们的无效队列。但是这样做和读取 state_state->top 之间存在差距。在清除无效队列和读取 state_stack->top 之间,任何事情都可能发生。核心可以服务中断,发生总线争用并且非常慢,您可以命名它 - 可以重新加载无效缓存行(并由另一个处理器重新无效)。基本上 - 无效队列可以重新填充。这意味着我们实际上不能相信 original_top 的值;我们可能正在读取一个实际上是错误的本地缓存行(我们还没有使它失效)并且这样做,错误地认为它的值为 NULL 并返回 0。
所以基本上,我看不出阅读障碍有什么帮助,因为在障碍之后但在您希望执行的实际阅读之前,任何事情仍然可能发生。
我在这里想念什么?