原子加载和存储与内存顺序放宽

Atomic load and store with memory order relaxed

本文关键字:内存 顺序 存储 加载      更新时间:2023-10-16

我读到的任何地方都看到强烈建议不要使用宽松的内存顺序,我想知道以下代码段是否是可以工作的例外之一,或者有任何我没有看到的后果。

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与"空指针"不同。它是唯一类型的特殊常量,可以转换为其他类型的空指针。