vector在多线程下的问题(转)


  最近在做项目的过程中,遇到STL中vector的多线程访问问题。问题大概是这样的:有一个全局的vector,一个写进程对该vector进行插入操作(push_back()),同时有一个读进程在监视该vector的内容并对其进行显示(操作:size(), at(i)),没有进行任何的线程同步,程序的编译没有任何问题,却一直出现运行时错误,主要是数组越界。  当时的考虑时:虽然vector不支持多线程,但是我的两个线程,一个写,一个却是只读,按理说不应该有问题,大不了有脏数据,但是我不在乎。网上有很多人说是线程同步问题,但是个人感觉不是这个问题。后来看了一篇网文之后才晃然大悟,其实是vector的大小动态分配所造成的问题。简单的说就是读进程和写进程在vector的内存动态重分配时内存地址不同步了(不知道说的对不对)。懒的再描述自己的具体问题了,直接把那篇网文贴上来,以供以后查看。

 

原文地址http://donghao.org/2008/10/vectorouaissiiaaieia.html

原文内容:

  程序出现了coredump,用gdb发现了出错的地方。

vector<size_t> seq_offset;
......
if(seq_id < seq_offset.size())
{
    seq_offset[seq_id];        //此处coredump
}

      没有超过vector的大小,访问是不应该有问题的,而且这一现象是偶然出现,所以怀疑是多线程的原因。果然在另一个线程里发现对seq_offset有 insert操作,insert本身不会影响访问,但是当vector大小不够的时候,insert会引发内存重新分配。STL代码(linux gcc-3.4.3 /usr/include/c++/3.4.3/bits)里,vector的insert会调用_M_fill_insert,而当空间不够时 _M_fill_insert会重新分配空间,并将相关数据结构指向新空间。

文件 vector.tcc 
324        std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish);        //销毁vector里的元素,即调用各元素的析构函数
325         _M_deallocate(this->_M_impl._M_start,                                           //收回存放各元素的空间,即free
326               this->_M_impl._M_end_of_storage - this->_M_impl._M_start);        
327         this->_M_impl._M_start = __new_start.base();                                //数据结构指向新的空间
328         this->_M_impl._M_finish = __new_finish.base();              
329         this->_M_impl._M_end_of_storage = __new_start.base() + __len;

      麻烦就在于当326行结束后,_M_start指向的是一块已经释放了的空间,这时候再有vector的访问操作(如 seq_offset[seq_id])当然就会coredump。其实STL完全可以先把_M_start赋给一个临时变量,然后_M_start指向 新空间,最后再释放临时变量指向的空间,这样可以保证在多线程下顺利运行。不过STL文档说了——它不支持多线程——所以这样做也没错。
      加锁也可以解决这个问题,不过那样太低效了,不予考虑。最后的解决方案是,用vector的reserve方法预先分配好内存,免得在使用中动态增长。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM