concurrent_vector无效数据

时间:2014-02-16 06:35:43

标签: c++ multithreading visual-c++ concurrency concurrent-vector

使用:VC ++ 2013

concurrency::concurrent_vector<datanode*> dtnodelst

偶尔我做dtnodelst->at(i) ....我收到的地址无效(0XCDCD .. ofc) 这不应该是因为我推回后的情况,我永远不会删除或删除任何itms(即使我删除它应该已经返回已删除的旧地址...但我不会删除所以,甚至不是案例)

dtnodelst itm = new dtnodelst ();
....
dtnodelst->push_back(itm);

关于可能发生的事情的任何想法?

P.S。我正在使用Windows线程池。有时候..我可以做800万次插入并找到并且一切都很好....但有时甚至200次插入和发现都会失败。我有点迷茫。任何帮助都会非常赞赏!!

感谢和最好的问候

实际代码为fyi

P.S。我是否遗漏了某些东西,或者过去的代码是否因为格式正确而感到痛苦?我记得它在...之前自动对齐... -_-

struct datanode {       
     volatile int nodeval;
     T val;
};
concurrency::concurrent_vector<datanode*> lst
inline T find(UINT32 key)
{
    for (int i = 0; i < lst->size(); i++)
    {
       datanode* nd = lst->at(i);
       //nd is invalid sometimes
       if (nd)  
       if (nd->nodeval == key)
       {
         return (nd->val);
       }
    }
    return NULL;
}
inline T insert_nonunique(UINT32 key, T val){
   datanode* itm = new datanode();
   itm->val = val;
   itm->nodeval = key;
   lst->push_back(itm);
   _updated(lst);                       
   return val;
}

2 个答案:

答案 0 :(得分:3)

问题是使用了concurrent_vector::size(),它不是完全线程安全的,因为你可以引用尚未构造的元素(内存中包含垃圾)。 Microsoft PPL库(在concurrency::命名空间中提供)使用concurrent_vector和TBB Reference的英特尔TBB实现:

  

size_type size() const |   返回:向量中的元素数。结果可能包括通过并发调用任何增长方法而分配但仍在构建的元素。

有关更多说明和可能的解决方案,请参阅my blog

在TBB中,最合理的解决方案是使用tbb::zero_allocator作为concurrent_vector的基础分配器,以便在size()计数之前用新零填充新分配的内存。

concurrent_vector<datanode*, tbb::zero_allocator<datanode*> > lst;

然后,条件if (nd)将过滤掉尚未准备好的元素。

答案 1 :(得分:-1)

volatile不能代替atomic<T>。在尝试提供同步时不要使用volatile

find调用的整个想法在并发上下文中没有意义。一旦函数迭代了一个值,它就可以被另一个线程变异为你正在寻找的值。或者它可能是您想要的值,但是变异为其他值。或者只要它返回false,就会添加您要搜索的值。这种功能的返回值完全没有意义。 size()具有所有相同的问题,这是您的实施永远不会起作用的一个很好的部分。

检查并发数据结构的状态是一个非常糟糕的主意,因为信息在您拥有它时就会变得无效。您应该设计不需要知道结构状态的操作,以便在操作时阻止所有突变。