原子加载和存储与内存顺序放宽
Atomic load and store with memory order relaxed
我读到的任何地方都看到强烈建议不要使用宽松的内存顺序,我想知道以下代码段是否是可以工作的例外之一,或者有任何我没有看到的后果。
class SessionHolder {
public:
void set_session(std::shared_ptr<Session> session) {
std::atomic_store_explicit(&_session, session, std::memory_order_relaxed);
}
std::shared_ptr<Session> get_session() const {
return std::atomic_load_explicit(&_session, std::memory_order_relaxed);
}
private:
std::shared_ptr<Session> _session;
};
原则上,当我做一个get_session
时,我不在乎我得到的是哪个会话,只要它是一个会话或 nullptr。但是,如果另一个线程执行存储(很少发生(,我希望最终在合理的延迟内获得该值。
- 据我了解,甚至不能保证我会得到那个值,只是我会得到一个在某个时间点存储在那里的值,但我总是可以得到 nullptr。
- 在实践中似乎有效,我可以期望它在某些情况下/平台失败(总是检索 nullptr(吗?
- 我可以只调整存储操作中的内存顺序来解决这个问题吗?例如
memory_order_release
将更改传播到另一个线程?
有关如何使用此类的更多上下文:
基本上,我有某种不断生成数据的流。在某个点,客户端进程可能会连接(启动会话(并开始侦听此数据。生产者线程不断写入流,如果没有活动会话,则丢弃数据,否则发送到客户端。当客户端连接到此流并设置会话时,某个时间点(不经常(的另一个线程
。生产者线程必须尽可能少地争用,即使这意味着缺少一些消息。
据我了解,甚至不能保证我会得到那个值,只是我会得到一个在某个时间点存储在那里的值,但我总是可以得到 nullptr。
是的,假设每次调用get_session
都会返回一个空指针,但不太可能。即使是宽松的内存顺序也提供的一个保证是,一旦特定线程观察到一个值,同一线程随后就无法观察到以前的值。因此,一旦特定线程开始观察非空指针,该线程将在后续调用get_session
中始终观察到非空指针(假设永远不会存储空指针(。
在实践中似乎有效,我可以期望它在某些情况下/平台失败(总是检索 nullptr(吗?
不是我知道的。
我可以只调整存储操作中的内存顺序来解决这个问题吗?例如
memory_order_release
将更改传播到另一个线程?
不。该标准没有提供任何方法来确保线程间通信在任何特定的时间内完成。只有实施才能提供这样的保证。
最后一点:nullptr
与"空指针"不同。它是唯一类型的特殊常量,可以转换为其他类型的空指针。
- 具有内存顺序的原子负载存储
- 原子加载和存储与内存顺序放宽
- 内存排序或读取-修改-写入操作,仅(读/写)内存顺序
- 理解C++内存顺序,我错了吗?
- 初始化值是否保证通过其自己的地址反映,而不考虑内存顺序
- 如果 RMW 操作没有任何变化,是否可以针对所有内存顺序对其进行优化
- 多个线程之间的获取-释放内存顺序
- 松弛的内存顺序会导致无限循环吗?
- 是否可以使用松弛的内存顺序来观察条件?
- 共享指针析构函数中的内存顺序
- C++中的类私有成员的内存顺序是否得到保证?
- 将fetch_add与宽松的内存顺序返回唯一值
- 混合放松和释放获取内存顺序
- 使用C++原子库,我应该使用什么样的内存顺序进行加载,然后进行比较交换
- 当某些错误可以接受时,顺序加载存储原子的内存顺序应该是什么
- 获取释放内存顺序与顺序一致性不同的实际示例是什么?
- 发行语义中的内存操作 - C 11的内存顺序
- 我应该为等待工作线程的主线程使用哪种内存顺序
- OpenMP原子内存顺序
- "acquire" 和"consume"内存顺序有何不同,何时"consume"可取?