无锁环形缓冲区boost示例中的内存排序
memory ordering in boost example of lock-free ring buffer
当我阅读boost atomics关于无等待环形缓冲区实现的示例时:
https://www.boost.org/doc/libs/1_66_0/doc/html/atomic/usage_examples.html#boost_atomic.usage_examples.example_ringbuffer
我想知道是否需要memory_order_acquire
if (next_head == tail_.load(boost::memory_order_acquire))
似乎memory_order_relaxed也应该工作。我的论点是
value = ring_[tail];
发生在之前
tail_.store(next(tail), boost::memory_order_release)
在pop((调用中。因此,我们确信数据在作为存储在push((调用中之前已经被读取
ring_[head] = value;
为了便于参考,我粘贴了下面的整个boost示例代码。谢谢
#include <boost/atomic.hpp>
template<typename T, size_t Size>
class ringbuffer {
public:
ringbuffer() : head_(0), tail_(0) {}
bool push(const T & value)
{
size_t head = head_.load(boost::memory_order_relaxed);
size_t next_head = next(head);
if (next_head == tail_.load(boost::memory_order_acquire))
//上面的tail_.load是否可以使用boost::memory_order_relaxed?
return false;
ring_[head] = value;
head_.store(next_head, boost::memory_order_release);
return true;
}
bool pop(T & value)
{
size_t tail = tail_.load(boost::memory_order_relaxed);
if (tail == head_.load(boost::memory_order_acquire))
return false;
value = ring_[tail];
tail_.store(next(tail), boost::memory_order_release);
return true;
}
private:
size_t next(size_t current)
{
return (current + 1) % Size;
}
T ring_[Size];
boost::atomic<size_t> head_, tail_;
};
一个原因是按顺序:
if(next_head == tail_.load(boost::memory_order_acquire))
return false;
ring_[head] = value; // A non-atomic store.
CCD_ 1确保以下非原子存储不会被重新排序为在tail_
的加载之前。
另一方面,memory_order_relaxed
不阻止重新排序,因此在这里是不够的。
(假设boost::memory_order
等于std::memory_order
。(
发布获取订单:
在强排序系统(x86、SPARC TSO、IBM大型机等(上,发布-获取排序在大多数操作中都是自动的。没有针对该同步模式发出额外的CPU指令;只有某些编译器优化会受到影响(例如,禁止编译器将非原子存储移动到原子存储发布之后,或在原子加载获取之前执行非原子加载(。在弱序系统(ARM、安腾、PowerPC(上,使用特殊的CPU负载或内存围栏指令。
据我所见,push()
中的tail_.load(boost::memory_order_acquire)
和pop()
中的head_.load(boost::memory_order_acquire)
都可以放松并用memory_order_acquire
0替换。
- C++内存模型中的确切规则阻止在获取操作之前重新排序
- 危险指针的内存排序
- 内存排序在提升::无锁:队列
- 内存排序或读取-修改-写入操作,仅(读/写)内存顺序
- 针对某些特定用例的C++原子内存排序
- 无锁环形缓冲区boost示例中的内存排序
- C++具有内存排序的原子增量
- 从矢量中最快的擦除元素或更好地利用内存(排序基数)
- C++原子增量内存排序
- C++中的无锁数据结构=只使用原子和内存排序
- C++内存排序一致性
- 将C++内存排序映射到Java
- std::atomic::load的内存排序行为
- x86 体系结构上的内存排序限制
- 具有两个原子的自旋锁的最小限制内存排序
- 使用获取-释放内存排序的传递同步
- 内存排序、指令重新排序和缺乏发生前关系
- C++11 原子内存排序 - 这是宽松(释放-消耗)排序的正确用法吗?
- 使用atomic_flag旋转锁进行内存排序
- C++11内存排序-差异