原子载荷和存储与内存顺序放松

问题描述 投票:2回答:1

在我看到的任何地方,我都看到强烈的建议不要使用轻松的记忆顺序,我想知道下面这段代码是否会起作用,或者我没有看到任何后果。

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会将更改传播到另一个线程吗?

有关如何使用此类的更多上下文:

基本上,我有一些不断产生数据的流。在某个时刻,客户端进程可以连接(启动会话)并开始侦听此数据。生产者线程持续写入流,如果没有活动会话,则数据被丢弃,否则发送到客户端。在客户端连接的某个时刻(不经常),另一个线程到达此流并设置会话。

生产者线程必须尽可能少地争用,即使这意味着缺少一些消息。

c++ c++11 concurrency memory-model memory-barriers
1个回答
2
投票

据我所知,甚至不能保证我会得到那个值,只是我会在某个时间点得到一个存储在那里的值,但我总能得到nullptr。

是的,假设每次调用get_session都会返回一个空指针,但不太可能。甚至放宽内存顺序提供的一个保证是,一旦特定线程观察到一个值,相同的线程就不能随后观察到先前的值。因此,一旦特定线程开始观察非空指针,该线程将始终在后续调用get_session时观察到非空指针(假设永远不存储空指针)。

在实践中似乎工作,我可以期望它在某些情况/平台中失败(总是检索nullptr)吗?

不是我知道的。

我可以调整商店操作中的内存顺序来解决这个问题吗?例如memory_order_release会将更改传播到另一个线程吗?

不可以。该标准没有提供任何方法来确保在任何特定时间内完成线程间通信。只有实施才能提供这样的保证。

最后一点说明:nullptr与“空指针”不同。它是一个唯一类型的特殊常量,可以转换为另一种类型的空指针。

© www.soinside.com 2019 - 2024. All rights reserved.