我在所有阅读的地方都看到强烈建议不要使用宽松的内存顺序,我想知道下面的代码是否是可以工作的例外之一,还是有我看不到的任何后果。
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,我都不会在意哪个会话。但是,如果另一个线程进行存储(这种情况很少发生),我希望最终在合理的延迟内获得该值。
memory_order_release
会将更改传播到另一个线程吗?有关如何使用此类的更多上下文:
基本上,我有某种不断产生数据的流。在某个时候,客户端进程可能会连接(开始会话)并开始侦听此数据。生产者线程将连续写入流,如果没有活动会话,则数据将被丢弃,否则将被发送到客户端。当客户端连接时,在某个时间点(不是经常)的另一个线程到达此流并设置会话。
生产者线程必须具有尽可能少的竞争,即使这意味着丢失一些消息。
答案 0 :(得分:2)
据我了解,甚至不能保证我会得到该值,只是我会得到某个时间点存储在其中的值,但我总能得到nullptr。
是的,假设每次对get_session
的调用都可能返回空指针,但这不太可能。甚至宽松的内存顺序提供的一种保证是,一旦特定线程观察到一个值,则同一线程随后将无法观察到先前的值。因此,一旦特定线程开始观察到非空指针,则该线程在随后的对get_session
的调用中将始终观察到非空指针(假定从未存储空指针)。
在实践中似乎可行,我是否可以指望它在某些情况下/平台上会失败(总是检索nullptr)?
不是我所知道的。
我可以仅在存储操作中调整存储顺序吗?例如
memory_order_release
会将更改传播到另一个线程吗?
不。该标准没有提供任何方法来确保线程间通信在任何特定时间内完成。只有实现可以提供这种保证。
最后一个注释:nullptr
与“空指针”不同。这是唯一类型的特殊常量,可以将其转换为另一种类型的空指针。