[C/C++标准库]_[初级]_[std:vector的多线程读写有关问题]
[C/C++标准库]_[初级]_[std::vector的多线程读写问题]
目前还没找到原因,有一种可能是this->-Myfirst的值debug时没有变化,不是它的问题, 那可能就是pointer对象在改变容量时改变了对象的存储位置,时间关系没有深入研究.
场景:
1. 有时候需要使用vector 或 map作为多线程的共享变量, map是tree结构, 读和写方法都不是线程安全的, 即同时读写会有崩溃的现象.
2. std::vector直观来说只用push_back和[] 下标访问操作应该没问题,push_back往后边加对象, 索引值只访问已经存储的变量(预先求size).注意, 这里不会删除vector元素.
可惜,这种多线程操作还是会崩溃. 单线程写和单线程读!!!
看代码:
test_vector.cpp
#include "gtest/gtest.h"
#include <vector>
#include <iostream>
#include <Windows.h>
#include "pthread.h"
class A
{
public:
A(int i):i_(i){}
int i_;
};
void* first = NULL;
void* second = NULL;
static void* Push(void* data)
{
std::vector<A*>& vec = *(std::vector<A*>*)data;
vec.push_back(new A(-1));
first = std::addressof(vec._Myfirst);
//std::cout << first << std::endl;
for(int i = 0; i< 100000;++i)
{
vec.push_back(new A(i));
//Sleep(2);
}
return NULL;
}
static void* Read(void* data)
{
std::vector<A*>& vec = *(std::vector<A*>*)data;
int size = vec.size();
while((size = vec.size())!= 100000)
{
for(int i = 0;i<size;++i)
{
A* a = vec[i];
second = std::addressof(vec._Myfirst);
std::cout << "a->i_: " << a->i_ << std::endl;
}
}
return NULL;
}
TEST(test_vector,testVector)
{
std::vector<A*> a;
pthread_t t1;
pthread_create(&t1,NULL,&Push,&a);
pthread_detach(t1);
pthread_t t2;
pthread_create(&t2,NULL,&Read,&a);
pthread_detach(t2);
system("pause");
}
内存大小很正常:
崩溃的位置: a已经是无效的数值了.
看vector代码也没看出什么问题:
void push_back(_Ty&& _Val)
{ // insert element at end
if (_Inside(_STD addressof(_Val)))
{ // push back an element
size_type _Idx = _STD addressof(_Val) - this->_Myfirst;
if (this->_Mylast == this->_Myend)
_Reserve(1);
_Orphan_range(this->_Mylast, this->_Mylast);
_Cons_val(this->_Alval,
this->_Mylast,
_STD forward<_Ty>(this->_Myfirst[_Idx]));
++this->_Mylast;
}
else
{ // push back a non-element
if (this->_Mylast == this->_Myend)
_Reserve(1);
_Orphan_range(this->_Mylast, this->_Mylast);
_Cons_val(this->_Alval,
this->_Mylast,
_STD forward<_Ty>(_Val));
++this->_Mylast;
}
}
reference operator[](size_type _Pos)
{ // subscript mutable sequence
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() <= _Pos)
{ // report error
_DEBUG_ERROR("vector subscript out of range");
_SCL_SECURE_OUT_OF_RANGE;
}
#elif _ITERATOR_DEBUG_LEVEL == 1
_SCL_SECURE_VALIDATE_RANGE(_Pos < size());
#endif /* _ITERATOR_DEBUG_LEVEL */
return (*(this->_Myfirst + _Pos));
}
目前还没找到原因,有一种可能是this->-Myfirst的值debug时没有变化,不是它的问题, 那可能就是pointer对象在改变容量时改变了对象的存储位置,时间关系没有深入研究.
环境:
visual studio c++ 2010 sp1.
作为临时解决方案, 暂时用C数组来解决这个push_back和下标访问的问题,
test_carray.cpp
#include "gtest/gtest.h"
#include <vector>
#include <iostream>
#include <Windows.h>
#include "pthread.h"
class A
{
public:
A(int i):i_(i){}
int i_;
};
class S
{
public:
S()
{
index_ = 0;
count_ = sizeof(a)/sizeof(A*);
}
A* a[10000];
int index_;
int count_;
};
static void* Push(void* data)
{
S* s = (S*)data;
for(int i = 0; i< s->count_;++i)
{
s->a[i] = new A(i);
s->index_ = i;
//Sleep(2);
}
s->index_+=1;
return NULL;
}
static void* Read(void* data)
{
S* s = (S*)data;
int size = 0;
while((size = s->index_) < s->count_)
{
for(int i = 0;i<size;++i)
{
A* a = s->a[i];
std::cout << "a->i_: " << a->i_ << std::endl;
}
}
return NULL;
}
TEST(test_carray,testArray)
{
S s;
pthread_t t1;
pthread_create(&t1,NULL,&Push,&s);
pthread_detach(t1);
pthread_t t2;
pthread_create(&t2,NULL,&Read,&s);
pthread_detach(t2);
pthread_t t3;
pthread_create(&t3,NULL,&Read,&s);
pthread_detach(t3);
system("pause");
}
版权声明:本文为博主原创文章,未经博主允许不得转载。