STL中的list是否是线程安全的?

bugyouth 2004-09-12 10:56:34
我用多线程来操作list,但老是莫名其妙地崩溃,查了很长时间没有查到原因。STL中的list是否是线程安全的?在多线程操作list时,应当注意什么?
...全文
535 12 打赏 收藏 转发到动态 举报
写回复
用AI写文章
12 条回复
切换为时间正序
请发表友善的回复…
发表回复
yinzhaohui 2004-09-13
  • 打赏
  • 举报
回复
用例
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
//int CALLBACK WinMain(HINSTANCE hInstance,HINSTANCE hpreInstance,LPSTR cmdLine,int cmdcount)
{

int nRetCode = 0;

// 初始化 MFC 并在失败时显示错误
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: 更改错误代码以符合您的需要
_tprintf(_T("致命错误: MFC 初始化失败\n"));
nRetCode = 1;
}
else
{
// TODO: 在此处为应用程序的行为编写代码。
test();
}
return nRetCode;
}


typedef struct str_data
{
int a;
CString str;
}Data;

typedef CYQueueSyn<Data*> Queue;

unsigned int __stdcall threadin(void *param)
{
Queue *pqueue=(Queue *)param;
for(int i=0;i<1000;i++)
{
Data *data=new Data();
data->a=i;
data->str.Format("data=%d",i);
pqueue->inq(data);
//Sleep(100);
}

Data *data=new Data();
data->a=-1;
pqueue->inq(data);
printf("in end!\n");
return 0;
}

unsigned int __stdcall threadout(void *param)
{
Queue *pqueue=(Queue *)param;
Data *pdata;
while(1)
{
try
{
pdata=pqueue->outq();
if(pdata->a==-1)
throw CYException("end");
printf("%d %s\n",pdata->a,pdata->str);
delete pdata;
}
catch(...)
{
delete pdata;
break;
}
}
printf("out end!\n");
return 0;
}

void test()
{
Queue queue(1000);
HANDLE thread[20];
unsigned int threadId[20];
for(int i=0;i<10;i++)
{
thread[i]=(HANDLE)_beginthreadex(NULL,0,threadin,&queue,0,&threadId[i]);
}

for(int i=10;i<20;i++)
{
thread[i]=(HANDLE)_beginthreadex(NULL,0,threadout,&queue,0,&threadId[i]);
}
WaitForMultipleObjects(20,thread,true,INFINITE);
}
bugyouth 2004-09-13
  • 打赏
  • 举报
回复
多谢,您的程序没有出现过崩溃情况吗?
再加100分,继续
yinzhaohui 2004-09-13
  • 打赏
  • 举报
回复
#pragma once

template <class TYPE>
class CYQueueSyn
{
public:
std::list<TYPE> queue;
int m_outtime;
HANDLE m_readSem;
HANDLE m_writeSem;
HANDLE m_synObject;

public:
CYQueueSyn(int length,int outtime=INFINITE);
virtual ~CYQueueSyn(void);
public:
void inq(TYPE type);
TYPE outq();
void free();

};

template<class TYPE>
void CYQueueSyn<TYPE>::free()
{
int size=(int)queue.size();
for(int i=0;i<size;i++)
delete queue.back();
queue.clear();
}

template<class TYPE>
CYQueueSyn<TYPE>::CYQueueSyn(int length,int outtime)
{
m_readSem=CreateSemaphore(NULL,0,length,NULL);
m_writeSem=CreateSemaphore(NULL,length,length,NULL);
m_synObject=::CreateMutex(NULL,false,NULL);
}

template<class TYPE>
CYQueueSyn<TYPE>::~CYQueueSyn()
{
CloseHandle(m_readSem);
CloseHandle(m_writeSem);
CloseHandle(m_synObject);
}

template<class TYPE>
void CYQueueSyn<TYPE>::inq(TYPE type) throw(CYException)
{
int rVal=WaitForSingleObject(m_writeSem,m_outtime);

if(rVal==WAIT_OBJECT_0)
{
if(WaitForSingleObject(m_synObject,INFINITE)==WAIT_OBJECT_0)
{
queue.push_back(type);
ReleaseMutex(m_synObject);
}
}
else if(rVal==WAIT_TIMEOUT)
{
throw CYException("1 TIMEOUT");
}
else if(rVal==WAIT_ABANDONED)
{
throw CYException("-1 ERROR");
}
ReleaseSemaphore(m_readSem,1,NULL);
}

template<class TYPE>
TYPE CYQueueSyn<TYPE>::outq() throw(CYException)
{
TYPE value;
int rVal=WaitForSingleObject(m_readSem,m_outtime);
if(rVal==WAIT_OBJECT_0)
{
if(WaitForSingleObject(m_synObject,INFINITE)==WAIT_OBJECT_0)
{
value=queue.front();
queue.pop_front();
ReleaseMutex(m_synObject);
}
}
else if(rVal==WAIT_TIMEOUT)
{
throw CYException("1 TIMEOUT");
}
else if(rVal==WAIT_ABANDONED)
{
throw CYException("-1 ERROR");
}
ReleaseSemaphore(m_writeSem,1,NULL);
return value;
}



yinzhaohui 2004-09-13
  • 打赏
  • 举报
回复
不是多线程安全的
The SGI implementation of STL is thread-safe only in the sense that simultaneous accesses to distinct containers are safe, and simultaneous read accesses to to shared containers are safe. If multiple threads access a single container, and at least one thread may potentially write, then the user is responsible for ensuring mutual exclusion between the threads during the container accesses.

This is the only way to ensure full performance for containers that do not need concurrent access. Locking or other forms of synchronization are typically expensive and should be avoided when not necessary.

It is easy for the client or another library to provide the necessary locking by wrapping the underlying container operations with a lock acquisition and release. For example, it would be possible to provide a locked_queue container adapter that provided a container with atomic queue operations.

bugyouth 2004-09-13
  • 打赏
  • 举报
回复
各位有没有一个详细且可用的例子,让我学习一下。分数不是问题。
DentistryDoctor 2004-09-12
  • 打赏
  • 举报
回复
STL是线程安全的,对于list,所谓的线程安全也只是说的它的链表操作,对于在线程间共享的数据,无论什么情况你都应该使用同步机制加以保护,如果不跨进程,临界区是很好的选择。
oyljerry 2004-09-12
  • 打赏
  • 举报
回复
估计还是要看看线程方面的处理有没有问题
hzhxxx 2004-09-12
  • 打赏
  • 举报
回复

应该是安全的, STL 自己说的啊
9731boy 2004-09-12
  • 打赏
  • 举报
回复
list 应该是线程安全的.应该是你的互斥没有做好.
另外也有可能是你程序其他方面的问题.你可以一步步的排除看看
bugyouth 2004-09-12
  • 打赏
  • 举报
回复
up
bugyouth 2004-09-12
  • 打赏
  • 举报
回复
我已经在线程函数中设置了Event
9731boy 2004-09-12
  • 打赏
  • 举报
回复
如果是操作公用内存的话.最好用互斥
容器类是隐式共享(implicitly)的,可重入(reentrant)的和线程安全的。并且在速度上进行了优化,内存占用少,内联代码扩展少,从而可以产生更小的可执行文件。 为容器遍历提供了两种迭代器(Java-style,STL-style),并且QT提供了foreach关键字,更加方便元素遍历。其,Java风格的迭代器更容易使用,特别是对于Java工作人员来说,它提供了高层次的函数;然而,STL风格的迭代器会更高效,并且可以和Qt和STL的通用算法结合使用。 Qt的容器和STL的类似,也分为序列式容器和关联式容器。 序列式容器有:QList,QLinkedList,QVector,QStack,QQueue。对大部分应用程序来说,QList都是一个很好的选择。尽管它在底层被实现为一个array-list,但它为我们提供了非常快速的添加操作,包括在头部添加和在尾部添加。如果你确实需要一个linked-list,可以使用QLinkedList;如果你想确保你的元素占用连续的内存空间,可以使用QVector。而QStack和QQueue是两个提供了LIFO和FIFO语义的方便类。 除了序列式容器,Qt还提供了关联式容器:QMap,QMultiMap,QHash,QMultiHash,QSet。这些容器存储的都是key-value对。其,"Multi"容器又支持一个key可以关联多个value。"Hash"容器通过使用一个hash函数而不是二分搜索提供了更快速的查找操作。

16,473

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧