C++ Chase-lev-deque中的原子存储

C++ Chase-lev-deque中的原子存储,c++,atomic,deque,work-stealing,C++,Atomic,Deque,Work Stealing,我正在实现Chase-lev-deque,这篇论文的基础是:“针对弱内存模型的正确有效的工作窃取”。在本文中,它要求deque有一个带有原子元素的缓冲区: struct Deque { std::atomic<size_t> size; std::atomic<int> buffer[]; } struct-Deque{ std:原子尺寸; std::原子缓冲区[]; } 为什么缓冲区中的元素的类型是std::atomic而不是普通的int?因为缓冲区元素是由

我正在实现Chase-lev-deque,这篇论文的基础是:“针对弱内存模型的正确有效的工作窃取”。在本文中,它要求deque有一个带有原子元素的缓冲区:

struct Deque {
  std::atomic<size_t> size;
  std::atomic<int> buffer[];
}
struct-Deque{
std:原子尺寸;
std::原子缓冲区[];
}

为什么缓冲区中的元素的类型是
std::atomic
而不是普通的
int

因为缓冲区元素是由不同的线程读取/写入的,并且在写入和后续读取之间并不总是有“发生在之前”的关系。因此,如果缓冲区元素不是原子的,那么就会出现数据竞争

如果您感兴趣,可以看看我对chase lev deque的实现:

更新

问题是索引可能会缠绕在一起。假设一个调用steal的线程在读取
top
bottom
之后,但在从缓冲区读取项目之前,可能会挂起。如果同时索引环绕,则该项可能会被某些推送操作覆盖。因此,steal中的加载操作不会与该存储有“发生之前”关系

本标准对数据竞争的定义如下:

如果一个程序在不同的线程中包含两个冲突的操作,则该程序的执行包含一个数据竞争,其中至少一个操作不是原子的,并且两个操作都不在另一个线程之前发生

由于所描述的示例没有提供缓冲区上的读写操作之间的before关系,因此如果缓冲区不是原子的,这将是一场数据竞争。然而,原子永远无法参与数据竞争,因此通过使缓冲区原子化,我们完全可以防止由非同步访问引起的任何数据竞争(即使这样的操作被放松)


请注意,这只是为了防止缓冲区上操作的数据争用而必需的。推送和窃取操作之间的实际同步是通过底部的操作进行的。

读/写缓冲区元素不是通过
顶部
底部
索引上的更新进行同步吗?不一定。。。问题是索引可能会缠绕在一起。假设一个调用steal的线程在读取top和bottom之后,但在它可以从缓冲区读取项之前,可能会被挂起。如果同时索引环绕,则该项可能会被某些推送操作覆盖。因此,steal中的加载操作不会与该存储有“发生之前”关系,如果缓冲区不是原子的,这将是一场数据竞争。但是为什么使用
std::memory\u order\u released
读取/写入元素可以解决数据竞争?松弛内存顺序不与其他操作同步。请你详细说明一下细节好吗?谢谢@我已经更新了我的答案以提供更多细节。如果还有什么不清楚的地方,请告诉我。