C++ 并发向量无效数据

C++ 并发向量无效数据,c++,multithreading,visual-c++,concurrency,concurrent-vector,C++,Multithreading,Visual C++,Concurrency,Concurrent Vector,使用:VC++2013 concurrency::concurrent_vector<datanode*> dtnodelst 对可能发生的事情有什么想法吗 p、 我正在使用windows线程池。有时。。我可以做八百万的插入和查找,一切都很好。。。。但有时即使是200次插入和查找也会失败。我有点迷路了。任何帮助都将不胜感激 谢谢并致以最良好的问候 供参考的实际代码 p、 在美国,我是否遗漏了一些东西,或者是因为使用了正确的格式编写了过去的代码而感到痛苦?我记得它在…-之前是自动对齐

使用:VC++2013

concurrency::concurrent_vector<datanode*> dtnodelst
对可能发生的事情有什么想法吗

p、 我正在使用windows线程池。有时。。我可以做八百万的插入和查找,一切都很好。。。。但有时即使是200次插入和查找也会失败。我有点迷路了。任何帮助都将不胜感激

谢谢并致以最良好的问候

供参考的实际代码 p、 在美国,我是否遗漏了一些东西,或者是因为使用了正确的格式编写了过去的代码而感到痛苦?我记得它在…-之前是自动对齐的

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;
}
struct datanode{
易失性内质网;
T值;
};
并发::并发向量lst
内联T查找(UINT32键)
{
对于(int i=0;isize();i++)
{
数据节点*nd=lst->at(i);
//nd有时无效
如果(nd)
如果(nd->nodeval==键)
{
返回(nd->val);
}
}
返回NULL;
}
内联T插入不均匀(UINT32键,T值){
datanode*itm=新的datanode();
itm->val=val;
itm->nodeval=键;
lst->推回(itm);
_更新(lst);
返回val;
}

问题在于使用的是
并发向量::size()
,它不是完全线程安全的,因为您可以获得对尚未构造的元素(其中内存包含垃圾)的引用。Microsoft PPL库(在
并发::
命名空间中提供)使用英特尔TBB实现
并发向量,TBB表示:

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

有关更多解释和可能的解决方案,请参阅

在TBB中,最合理的解决方案是用作
并发_vector
的底层分配器,以便在size()也将其计数之前用零填充新分配的内存

concurrent_vector<datanode*, tbb::zero_allocator<datanode*> > lst;
并发向量lst;

然后,条件
if(nd)
将过滤掉尚未就绪的元素。

volatile
不能替代
原子
。不要在尝试提供同步时使用
volatile

在并发上下文中,
find
调用的整个想法没有意义。一旦函数在一个值上迭代,它可能会被另一个线程变异为您要查找的值。或者它可能是您想要的值,但经过变异后会变成其他值。或者,当它返回
false
时,将添加您正在查找的值。这样一个函数的返回值将毫无意义
size()
具有所有相同的问题,这也是实现永远无法工作的原因之一


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

潜在的
volatile
误用在这里不起作用,因为据我所知,指针
datanode*nd
获取的地址无效-这就是我的答案。请删除downvotemoreover,说方法不好是不公平的。例如,用户可能希望创建一个并发快照,或者可能希望手动同步对元素的访问—例如tbb::和ppl::concurrent_unordered_映射。由于某种原因,zero_分配器从当前repo:blog链接中消失。您能否简单列出SO答案中的3种解决方案?
concurrent_vector<datanode*, tbb::zero_allocator<datanode*> > lst;