使用std::map时必须互斥的所有操作/函数是什么?
What are all the operations/functions that has to be Mutexed when using std::map
我有一个std::map,其中tuple作为键和值的向量的组合,如
using ReqList=map<const Attrib,vector<REQ>,less<key_comp>>;
//属性是一个元组
对于这个映射,线程将查找键,如果键是新的,则插入;如果已经有键,则填充向量,然后进行某种形式的删除,如
ReqList l;
begin(l[A])=move(l[A].back());
//从值向量中移除第一个元素
我一直在做插入,查找,操作值,并删除(第一个元素)…那么,是否每个提到的操作或函数调用都需要被互斥?或者我只能把某些东西放在互斥锁下。map是否提供任何默认同步?
这其实很简单:如果你在"从map中读取"的同时"写入",那么你需要同步这些操作——例如用互斥锁保护它们。
这里的"写入到映射"是指调用映射的任何非const成员函数,而"从映射中读取"是指调用任何const成员函数。
当同时时,我的意思是有多个线程可以写入或读取映射。因此,单线程程序不需要同步。如果你在某个时间点写映射,然后绝对肯定地知道不会再写了,那么在那之后所有的读映射都可以不同步地进行。例如,如果您在一个线程的排序工厂函数中设置了一个映射,并且在设置之后再也不写入它,那么任何其他线程都可以不同步地从它读取。注意,当map超出作用域时,它的析构函数将运行,并将其写入;在此之前,所有可能的非同步读取必须已经完成。
如果你有一个线程从map读取数据,另一个线程向map写入数据,并且你不知道这些操作是如何相互同步的,互斥所有。保护对地图的每个访问。标准容器不提供保证,也不可能同步。
一般来说,作为经验法则,如果您对任何对象调用的所有方法都是const,则不需要围绕它进行同步。只要你对它做了一个非const操作,你就需要在每次触摸它的时候同步。
这不是万无一失的,这是一个经验法则,例如,一个函数可以声明自己为const,然后抛弃const,做一些危险的事情,或者它可以声明成员是可变的,所以即使是const,也让自己接触它。反过来也是正确的,你可以使用无锁编程技术来避免同步和保持一致性。
From [res.on.data.][/2]我们有
c++标准库函数不能直接或间接地修改当前线程以外的线程可以访问的对象(1.10),除非这些对象是通过函数的非const参数直接或间接访问的,包括this。
因此所有非const方法都允许修改状态,而所有const
函数都不能修改对象的状态。
经验法则是,如果你的数据在多个线程之间共享,并且至少有一个线程是写线程,那么你需要同步。
template<class T>
struct rw_locked {
template<class F>
auto read( F&& f ) const {
auto lock = read_lock();
return std::forward<F>(f)(t);
}
auto write( F&& f ) {
auto lock = write_lock();
return std::forward<F>(f)(t);
}
private:
auto read_lock() const {
return std::shared_lock<std::shared_timed_mutex>(m);
}
auto write_lock() {
return std::unique_lock<std::shared_timed_mutex>(m);
}
mutable std::shared_timed_mutex m;
T t;
};
现在只需:
rw_locked< std::map< int, int > > m;
m.read( [&](auto&&m) {
// code to read
} );
m.write( [&](auto&&m) {
// code to write
} );
,它将在大多数情况下正确保护。
从技术上讲,您可以在读锁中调用非const begin
,并且它将被定义,但通过结果迭代器写入将不会被定义。所以上面的代码不能让你得到非常量迭代器。
不要在上面的代码中返回指向map
中的数据的迭代器或指针,否则它不会保护你。
- 我可以在 C++ 中的函数体之外进行操作吗?
- 如何在信号处理程序和普通函数中对全局变量进行互斥读写操作
- C++ 随机数生成器:尝试将结果作为向量获取,但通过制作 void 函数来执行此操作而出现错误
- 无法调用成员函数,尝试正确执行此操作仍然失败
- 不执行任何操作的函数调用C++
- 如何实现对序列对进行操作的C++元函数
- 某些 boost::asio 异步函数是否将处理程序连接到操作,以便处理程序被触发一次?
- 为表示一个或多个操作的C++函数的int参数寻找类型安全的替换
- 在函数中操作 std::array
- 避免通过操作从私有构造函数间接实例化
- 如果普通默认构造函数不执行任何操作,为什么我们不能使用 malloc 创建平凡可构造的对象?
- 如何检测函数是否执行IO操作
- 如何将操作委托给函数返回
- 在MySql中使用字符串操作函数有什么问题
- Rcpp 中"List"的操作函数 - 类似于 R 中的"Reduce function"
- 无操作函数模板
- 按位操作函数
- 当人们想操作函数中的指针时,为什么要传入双指针
- 如何在c++中操作函数以根据条件输出不同的结果
- 使用std::map时必须互斥的所有操作/函数是什么?