为什么这个使用boost的并发Hasmap不起作用
Why does this Concurrent Hasmap using boost not work
我有以下并发哈希映射:
template<typename Key, typename Value>
class ConcurrentMap
{
public:
ConcurrentMap() {};
bool has(Key k)
{
boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
return m.find(k) != m.end();
}
void set(Key k, Value v)
{
boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
// set k, v
if(m.find(k) != m.end())
{
boost::upgrade_lock<boost::shared_mutex> valueLock(*valueAccess[k]);
boost::upgrade_to_unique_lock<boost::shared_mutex> valueUniqueLock(valueLock);
m.at(k) = v;
}
// insert k, v
else
{
lock.unlock();
boost::upgrade_lock<boost::shared_mutex> schemaLock(schemaAccess);
boost::upgrade_to_unique_lock<boost::shared_mutex> schemaUniqueLock(schemaLock);
boost::shared_ptr<boost::shared_mutex> mtx = boost::make_shared<boost::shared_mutex>();
valueAccess.insert(std::pair<Key, boost::shared_ptr<boost::shared_mutex> >(k, mtx));
m.insert(std::pair<Key,Value>(k,v));
}
}
Value get(Key k)
{
boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
return m.at(k);
}
bool get(Key k, Value& v)
{
boost::shared_lock<boost::shared_mutex> lock(schemaAccess);
if(m.find(k) != m.end()){
v = m.at(k);
return true;
}
return false;
}
private:
std::map<Key, Value> m;
std::map<Key, boost::shared_ptr<boost::shared_mutex> > valueAccess;
boost::shared_mutex schemaAccess;
//http://stackoverflow.com/questions/36468270/how-to-use-a-boostmutex-as-the-mapped-type-in-stdmap/36469809?noredirect=1#comment60552035_36469809
};
以及以下用法:
ConcurrentMap<int, cv::Mat> mapper;
void worker1(){
int counter = 0;
while(1){
boost::this_thread::sleep(boost::posix_time::milliseconds(5));
cv::Mat img = cv::Mat(1920,1080, CV_64F);
cout << "w1" << counter++ << endl;
mapper.set(0,img);
}
}
void worker2(){
int counter = 0;
while(1){
boost::this_thread::sleep(boost::posix_time::milliseconds(5));
cout << "w2" << counter++ << endl;
cv::Mat img;
if(!mapper.get(0, img)) continue ;
cout << img.rows << endl;
cout << "done" << endl;
}
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "loading_area_concat");
boost::thread worker1_;
boost::thread worker2_;
worker1_ = boost::thread(worker1);
worker2_ = boost::thread(worker2);
ros::spin();
return 0;
}
*** Error in `/home/raaj/catkin_ac2/devel/lib/loading_area/loading_area_concat': free(): invalid pointer: 0x00007fb71c000078 ***
然而,我的代码在第二个线程的"get"部分不断崩溃。如果我评论出"得到",它就起作用了。要么是这样,要么如果我用下面的代码完全锁定get代码,它就会起作用:
boost::upgrade_lock<boost::shared_mutex> schemaLock(schemaAccess);
boost::upgrade_to_unique_lock<boost::shared_mutex> schemaUniqueLock(schemaLock);
我似乎不明白为什么会发生这种事。当我向哈希图中的密钥写入时,我正在锁定它,当我读取它时,写入程序不应该进来破坏内存,是吗?
您是否也尝试锁定get()并检查问题是否消失?从高级的角度来看,如果没有写入,则只读不需要锁定。如果有一些线程向该位置写入,则读取也需要受到保护,否则就会出现竞争条件(get()可能最终使用不再有效的东西)。
好吧,我看到了在get()中锁定解决问题的编辑,所以看起来确实是这样。
问题是,对不变内存的并发读取不需要锁定。但是,如果有并发写入,读取也需要锁定(针对写入,否则可能会发生各种奇怪的事情,如部分/交错读取等)。
相关文章:
- 控制允许动态运行c++的并发操作数
- 节俭并发:未解决的外部问题
- 并发/多线程:是否可以以这种方式生成相同的输出?
- 用于在并发环境中访问 MMIO 的软件模式
- C++中的并发哈希表
- 提升 asio 并发计时器取消问题与链
- C++具有基元类型的并发队列
- 使用简单两相锁定的并发程序
- C++ 按引用或值推送的并发队列
- 允许多个互斥锁所有者或指定数量的并发代码执行
- 琐碎并发代码的吞吐量不会随着线程数量的增加而增加
- 由并发无序映射查找线程调用的函数是否安全?
- 在迭代期间并发修改映射
- 并发安全堆栈接口方法:正确与否?
- 内存模型和并发
- 重塑Microsoft的并发::d iagnostic::span,也可以检测外部跨度
- 如何在 qt 中从另一个线程运行 qt并发时关闭程序
- 并发问题:如何只有一个线程通过关键部分
- Qt并发错误:用作初始值设定项的数组
- 为什么这个使用boost的并发Hasmap不起作用