使用: VC++,2013年
concurrency::concurrent_vector<datanode*> dtnodelst偶尔当我做dtnodelst->at(i)时..。我得到了一个无效的地址(0XCDCD)。( ofc)但我从来没有删除过,所以甚至不是这样的)
dtnodelst itm = new dtnodelst ();
....
dtnodelst->push_back(itm);对可能发生的事有什么想法吗?
附注:我正在使用windows线程池。有时候..。我可以做800万次插入和发现,一切都很好.但有时,即使是200个插入和发现也会失败。我有点迷路了。任何帮助都是非常感谢的!
谢谢并致以最良好的问候
作为fyi的实际代码
附注:我是遗漏了什么,还是对过去的代码有正确的格式感到痛苦?我记得那是自动对齐之前. -_-
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;
}发布于 2014-08-18 16:42:52
问题是使用不完全线程安全的concurrent_vector::size(),因为您可以获得尚未构造的元素的引用(其中内存包含垃圾)。Microsoft库(在concurrency::命名空间中提供它)使用concurrent_vector的Intel实现,TBB 参考文献说:
size_type size() const\返回:向量中的元素数。结果可能包括通过并发调用任何增长方法而被分配但仍在构建中的元素。
有关更多解释和可能的解决方案,请参见我的博客。
在TBB中,最合理的解决方案是使用tbb::zero_allocator作为concurrent_vector的底层分配程序,以便在size()也计算它之前用零填充新分配的内存。
concurrent_vector<datanode*, tbb::zero_allocator<datanode*> > lst;然后,条件if (nd)将筛选出尚未就绪的元素。
发布于 2014-08-18 17:06:57
volatile不能代替atomic<T>。不要在某些试图提供同步的尝试中使用volatile。
find调用的整个概念在并发上下文中没有意义。一旦函数对一个值进行迭代,它就可以被另一个线程更改为您要寻找的值。或者它可能是你想要的价值,但却变成了其他的价值。或者,当它返回false时,您正在寻找的值就会被添加。这样一个函数的返回值将完全没有意义。size()有所有相同的问题,这是为什么您的实现永远无法工作的一个很好的部分原因。
检查并发数据结构的状态是一个非常糟糕的想法,因为信息在你拥有它的时候就会失效。您应该设计不需要知道结构状态才能正确执行的操作,或者在操作时阻止所有的突变。
https://stackoverflow.com/questions/21808136
复制相似问题