c++ - 如何保证在存储发生之前加载完成?
问题描述
在下面的代码中,如何确保 ptr 在 *ptr 被加载/分配/“提取”之后才增加?
extern int arr[some_constexpr]; // assume pre-populated
extern int* ptr; // assume points to non-atomic arr
int a = *ptr;
// want "memory barrier/fence" here
++ptr;
原子指针会确保正确的排序/排序吗?
#include <atomic>
extern int arr[some_constexpr];
extern std::atomic<int*> ptr;
int a = *(ptr.load());
// implicit "memory barrier" achieved here by use of atomics?
ptr.store(ptr + 1);
这与两个线程之间共享的无锁队列有关。我想确保在更新指针之前与指针关联的数据不会丢失/损坏。
解决方案
When ptr
is std::atomic<int*>
, ++ptr
, or ptr++
orptr.fetch_add(1, std::memory_order_acq_rel)
确保没有在此操作之前/之后的加载/存储重新排序。
++ptr
, 或者ptr++
本质上是ptr.fetch_add(1, std::memory_order_seq_cst)
并且std::memory_order_seq_cst
几乎总是过度杀伤(不能举一个不是的例子)。
更高效的单一阅读器是:
int arr[some_constexpr];
std::atomic<int*> ptr;
int* p = ptr.load(std::memory_order_acquire);
int element = *p;
ptr.store(p + 1, memory_order_release);
以上基本上是如何boost::lockfree::spsc_queue
实现的。
作为旁注,boost::lockfree::spsc_queue
是一个真正的无等待(最强的非阻塞进度保证)队列。push
/pop
操作所做的是 1次relaxed
加载、1次acquire
加载和 1release
次存储,并且从根本上说不可能比具有 FIFO 顺序保证的速度更快地实现单生产者-单消费者队列(没有实施质量缺陷)。它通常用作所有其他队列的基准。你可能想调查一下。
推荐阅读
- node.js - 在 Google Oauth2 登录后将 JWT 传递给 UI 应用程序
- php - 在批处理 PHP 文件中添加 2 个值
- c# - C# 空锁块是否被“优化”掉了?
- sql-server - PostgreSQL 中 SQL Server hierarchyid 的等效数据类型是什么
- python - 如何在循环中忽略输入[Python]
- node.js - 同一集合上的mongodb内部循环
- c# - 为测试方法添加注释
- javascript - 我如何从阵列中获得下一次祈祷时间?
- firebase - 如何下载已在 firebase 免费域中上传的 Firebase 项目?
- python - 为什么谷歌镜头无法识别使用 PIL 库制作的图像上的 pyqrcode 制作的 QR?