如何实现std::atomic::load
How could std::atomic::load be implemented
假设我想要实现一个自己的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保护。
我想问两个问题:
- 如何实现正确版本的加载
- 不使用互斥而是使用无锁数据结构来实现
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
在您选择的标准库中的实现,了解许多血腥的细节。
相关文章:
- std::atomic和std::condition_variable wait,notify_*方法之间的区别
- 在 lambda 表达式中使用 std::atomic
- C++std::atomic在程序员级别保证了什么
- 如果在 2 个线程中使用,是否值得将size_t声明为 std::atomic?
- 在 C++20 之前和之后初始化 std::atomic
- std::atomic 和 std::mutex 的相对性能
- 简单使用 std::atomic 在两个线程之间共享数据
- Port pthread_cond_broadcast to std::atomic
- std::atomic中的任何内容都是免费等待的
- 为什么 std::atomic 构造函数在 C++14 和 C++17 中的行为不同
- std::atomic是如何实现的
- 使用 std::atomic 标志和 std::condition_variable 在工作线程上等待
- 为什么std::atomic的默认构造函数不默认初始化底层存储值
- 读取互斥对象范围之外的volatile变量,而不是std::atomic
- 为什么std::atomic中的所有成员函数都同时出现在有volatile和没有volatile的情况下
- 访问共享内存而不使用易失性、std::atomic、信号量、互斥锁和自旋锁
- 两个不同的进程,在同一地址上有 2 个 std::atomic 变量?
- 原子读取,然后使用 std::atomic 写入
- std::atomic::fetch_add是x86-64上的串行化操作
- 实际上,C++11 中 std::atomic 的内存占用量是多少?