STL list在多线程下使用需要注意的问题
2017-09-01 18:55
573 查看
最近做一个印刷品缺陷检测的图像处理的项目,是实时处理的。采用了多线程的方式,线程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不是线程安全的,在多线程下使用时一定要记得加锁。
我怀疑是由于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不是线程安全的,在多线程下使用时一定要记得加锁。
相关文章推荐
- 多线程下使用使用 UniDAC+MSSQL 需要注意的问题
- Qt 多线程与数据库操作需要注意的几点问题(QSqlDatabase对象只能在当前线程里使用)
- Delphi中多线程下使用使用 UniDAC+MSSQL 需要注意的问题
- FastMM内存管理器在使用多线程情况下需要注意的问题。
- Delphi中多线程下使用使用 UniDAC+MSSQL 需要注意的问题 .
- 项目问题总结二、hibernate和多线程同时使用需要注意
- 多线程下使用使用 UniDAC+MSSQL 需要注意的问题(使用CoInitialize)
- Delphi中多线程下使用使用 UniDAC+MSSQL 需要注意的问题(连接前调用CoInitialize)
- [置顶] java Vector 在多线程使用中需要注意的问题
- 使用Mount bind时需要注意的权限问题
- 使用jspSmartUpload包需要注意的问题
- 一个使用手机时需要注意的问题
- web程序使用Oracle需要注意的问题.
- 调试使用了函数模块的程序时需要注意的一个小问题
- vs.net中使用SuperMap需要注意的问题[转载]
- 使用模板模板缓冲时需要注意的几个问题
- 新手使用宽带路由器需要注意的问题
- Hibernate中使用自定义insert,update,delete语句需要注意的问题
- 调试使用了函数模块的程序时需要注意的一个小问题
- 使用字节与字符串转换时需要注意的问题