如何实现std::atomic::load

How could std::atomic::load be implemented

本文关键字:std atomic load 实现 何实现      更新时间:2023-10-16

假设我想要实现一个自己的std::atomic类型(当然我不想要,我只是出于好奇才这么问)。我将如何实现加载方法?我的猜测如下(m_mutex是用于锁定操作的互斥体,m_object是原子当前持有的对象):

T& load() {
    std::lock_guard<std::mutex> lck(m_mutex);
    return m_object;
}

显然,这将不起作用,因为当调用a.load().doSomething()时,对doSomething的调用将不受保护,因为m_object已经从load返回,并且不再由lock_guard保护。

我想问两个问题:

  1. 如何实现正确版本的加载
  2. 不使用互斥而是使用无锁数据结构来实现load的简单技术是什么

显然,这不起作用,因为当调用a.load().doSomething()对doSomething的调用将不受保护因为m_object,它已经从加载中返回,并且不受保护再也不用锁了。

这是该接口不可避免的副作用,任何实现都无法更改。如果你不仅想加载,还想保护它上的一些其他随机功能,那就另当别论了。

如果你认为std::atomic是安全的,那就不是了。

如何实现正确版本的加载?

template <typename T>
class atomic {
public:
  static_assert(std::is_trivially_copyable<T>(),
                "atomic<T> requires trivially copyable T");
  // ...
  // Ignores the memory ordering parameter and always provides
  // sequential consistency. This is *correct*, but possibly
  // sacrifices performance.
  T load(std::memory_order) const noexcept {
    std::lock_guard<std::mutex> guard{mtx_};
    return t_;
  }
private:
  std::mutex mtx_;
  T t_;
};

不使用互斥而是使用无锁数据结构来实现加载的简单技术是什么?

c++中的无锁数据结构是用无锁原子对象实现的。无锁原子对象的实现在标准C++的范围内是不可能的;它们需要来自编译器内部和/或特定于平台的内联汇编的支持,以执行具有适当排序保证的原子内存操作。看看std::atomic在您选择的标准库中的实现,了解许多血腥的细节。