c++ - 原子获取是否与互斥锁释放同步?
问题描述
我有一个对象,它unordered_map
使用字符串键和变量值存储一些设置。由于我的库可能会被多个线程使用,并且读取的数量很可能会大大超过写入的数量,因此我考虑过一个写入时复制实现,其中“get”操作是无锁的,而“put”操作是关键的部分,如示例中所示:
class Cfg {
using M = unordered_map<string,X>;
shared_ptr<const M> data;
mutex write_lock;
public:
X get(string key) {
shared_ptr<const M> cur_ver = atomic_load_explicit(&data, memory_order_acquire);
// Extract the value from the immutable *cur_ver
}
void put(string key, X value) {
lock<muted> wlock(write_lock);
// No need for the atomic load here because of the lock
shared_ptr<const M> cur_ver = data;
shared_ptr<const M> new_ver = ;// create new map with value included
// QUESTION: do I need this store to be atomic? Is it even enough?
atomic_store_explicit(&data, new_ver, memory_order_release);
}
}
只要获取/释放同步也会影响指向的数据而不仅仅是指针值,我有理由相信该设计是有效的。但是,我的问题如下:
- 这个工作需要锁内的原子存储吗?
- 或者原子获取是否会与作为“释放”操作的互斥锁同步?
解决方案
原子获取是否会与作为“释放”操作的互斥锁同步?
不,为了使获取操作与释放操作同步,获取操作必须观察释放操作的变化(或以该操作为首的潜在释放序列的某些变化)。
所以是的,你需要锁内的原子存储。由于您只使用获取/释放,因此无法保证get
会“看到”最新值put
,因此存储和加载操作之间没有总顺序。如果你想要那个保证,你必须使用memory_order_seq_cst
.
作为旁注 - 这个实现很可能不是无锁的,因为在大多数库实现atomic_load_explicit
中 forshared_ptr
不是无锁的。问题是您必须在一个原子操作中加载指针并取消引用该指针以增加 ref-counter 。这在大多数架构上是不可能的,因此atomic_load_explicit
通常使用锁来实现。
推荐阅读
- html - 为什么我用于 HTML 输入的 Size 属性不影响其宽度?
- mockito - mockito & powermock & powermockito 之间有什么联系和区别?
- postgresql - 聚集索引是否有单独的索引文件?
- java - Spring Batch - 将每个块项目合并到自定义项目编写器中的单个列表中
- c++ - 在 CGAL 中绘制彩色网格
- http - 如何增加 GraphDB 独立服务器的最大标头大小?
- flutter - 实现 authstatechanges 后调用两次的类
- curl - curl 命令使用其票证 ID 获取 jira 票证的数据
- asp.net-core - EF Core 5.0 RC1 表架构
- javascript - 在 API 获取期间总是收到此 CORS 错误