STL list在多线程下使用需要注意的问题

转 [https://blog.csdn.net/lujin0312/article/details/77776435]

最近做一个印刷品缺陷检测的图像处理的项目,是实时处理的。采用了多线程的方式,线程A负责从相机中取数据,线程B负责处理取到的数据。由于相机数据是以固定时间间隔过来,而且不能等待,所以我就想到利用一个双向链表来保存数据,线程A不停地往链表的尾部添加数据,线程B从链表头部取走数据,然后将表头节点pop出去。感觉上这两个线程虽然同时对链表进行操作,但是一个是往尾部追加数据,一个从头部取数据,似乎不会发生冲突,所以也没有加锁。但是运行过程中偶尔会出错,弹出itrator not refrenceable之类的错误。

我怀疑是由于list并不是线程安全的,所以两个线程同时对list进行操作会应发莫名其妙的问题。于是我写了一个简单的小程序测试一下。

#include "stdafx.h"
#include<iostream>
#include<process.h>
#include<windows.h>
#include<list>
using namespace std;
class CBaselock
{
public:
    CBaselock()
    {
      InitializeCriticalSection(&m_Sec);//初始化临界区
    }
    ~CBaselock()
    {
      DeleteCriticalSection(&m_Sec);
    }
    void Lock()
    {
      EnterCriticalSection(&m_Sec);
    }
    void UnLock()
    {
      LeaveCriticalSection(&m_Sec);
    }
private:
      CRITICAL_SECTION m_Sec;
};


class CTestList
{
public:
     CTestList() {};
     ~CTestList() {};
     long Start();
     static unsigned __stdcall PushThred(void * pThis)
     {
        CTestList * pthX = (CTestList*)pThis;   // the tricky cast  
        pthX->pushFunc();           // now call the true entry-point-function  
         return 1;                           // the thread exit code  
     }
     static unsigned __stdcall PopThred(void * pThis)
     {
        CTestList * pthX = (CTestList*)pThis;   // the tricky cast  
        pthX->popFunc();           // now call the true entry-point-function  
       return 1;                           // the thread exit code  
     }
     long pushFunc();
     long popFunc();
     list<int> m_list;
     CBaselock m_lock;
};


long CTestList::Start()
{
   _beginthreadex(NULL, 0, &PushThred, this, 0, 0);
    _beginthreadex(NULL, 0, &PopThred, this, 0, 0);
   return 1;
}
long CTestList::pushFunc()
{
       int index = 0;
      while (1)
      {
        //m_lock.Lock();
        printf("push:%d,list size:%d\n", index, m_list.size());
         m_list.push_back(index);
         //m_lock.UnLock();
         ++index;
        //Sleep(0);
      }
      return 1;
}
long CTestList::popFunc()
{
    while (1)
    {
          if (m_list.size() > 0)
         {
          //m_lock.Lock();
          printf("pop:%d,list size:%d\n", m_list.front(), m_list.size());
          m_list.pop_front();
          //m_lock.UnLock();
          //Sleep(0);
       }
    }
    return 1;
}


int main()
{
    CTestList testObj;
    testObj.Start();
    int a = 0;
    std::cin >> a;
    return 0;
}

在没有加锁时,测试时偶尔会弹出错误,于是老老实实加锁,测试没有报错了。

总结一点,stl list不是线程安全的,在多线程下使用时一定要记得加锁。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。