关于stl中std:queue线程安全问题

drinker_linux 2010-02-04 04:53:54
各位高手,请指教,谢谢!
c++-->stl中的std::queue是非线程安全的。
请问:1.为什么不作成线程安全的
2.到底什么是线程安全什么是线程非安全的,对于队列来说。一个线程读,一个线程写,不加锁会出什么问题。
...全文
2863 34 打赏 收藏 转发到动态 举报
写回复
用AI写文章
34 条回复
切换为时间正序
请发表友善的回复…
发表回复
jinchuan97 2011-02-14
  • 打赏
  • 举报
回复
试试下面这段代码,可以发现不加锁的问题了(运行一段时间后出现内存非法访问导致程序崩溃)
std::queue<BYTE*> g_queue;
::CRITICAL_SECTION g_cs;

DWORD WINAPI th1( LPVOID lpVoid )
{
while( true )
{
BYTE* buf = new BYTE[100];
//::EnterCriticalSection( &g_cs );
g_queue.push( buf );
//::LeaveCriticalSection( &g_cs );
Sleep(10);
}
}

DWORD WINAPI th2( LPVOID lpVoid )
{
while( true )
{
//::EnterCriticalSection( &g_cs );
if( g_queue.size()>0 )
{
BYTE* buf = g_queue.front();
g_queue.pop();
delete []buf;
}
//::LeaveCriticalSection( &g_cs );
Sleep(10);
}
}

int main()
{
::InitializeCriticalSection( &g_cs );

::CreateThread( NULL, 0, th1, NULL, 0, NULL );
::CreateThread( NULL, 0, th2, NULL, 0, NULL );

system("pause");
}
yangyunzhao 2010-10-23
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 drinker_linux 的回复:]

那么怎么才能出问题请问,
[/Quote]

出问题不是指程序抛异常吧。
应该是说程序运行效果和自己的想法不一致就叫出异常吧。不加锁几乎必然出问题,只是怎么出现而已。

你试试在多线程情况下,用用迭代器,不加锁。估计很快就出问题了
tompaz 2010-10-13
  • 打赏
  • 举报
回复
int读写简单,搞个复杂点的类试试就知道了
taodm 2010-02-09
  • 打赏
  • 举报
回复
呃,要向一个还不知道并发冲突是何物的人讲清楚可还真是实在很困难的。
如果楼主人品足够持续恒定一直好,你的代码就没啥问题。
必成桂 2010-02-04
  • 打赏
  • 举报
回复
当然不是线程安全的。

queue的底层实现一般是vector或者是deque。写操作的时候还是需要加锁的。
drinker_linux 2010-02-04
  • 打赏
  • 举报
回复
我已经试过,不管是去掉if(qqq.size()>1000)continue; 不管是怎么弄,程序都会正常运行啊
jackyjkchen 2010-02-04
  • 打赏
  • 举报
回复
[Quote=引用 27 楼 drinker_linux 的回复:]
可是这样的话,这个队列的大小启不是不确定上限了,如果无限的push数据,这样是不合理的吧。我先安你说的办,去掉那两行
[/Quote]
入队线程用低优先级,或者加个sleep,让它运行比出队慢即可。
drinker_linux 2010-02-04
  • 打赏
  • 举报
回复
可是这样的话,这个队列的大小启不是不确定上限了,如果无限的push数据,这样是不合理的吧。我先安你说的办,去掉那两行
jackyjkchen 2010-02-04
  • 打赏
  • 举报
回复
[Quote=引用 25 楼 drinker_linux 的回复:]
那么怎么才能出问题请问,
[/Quote]
if(qqq.size()>1000)
continue;
这一句去掉,有了这一句,你真正运行了不过N毫秒……
drinker_linux 2010-02-04
  • 打赏
  • 举报
回复
那么怎么才能出问题请问,
jackyjkchen 2010-02-04
  • 打赏
  • 举报
回复
if(qqq.size()>1000)
continue;
20分钟……真正进入队列的数据才1000个,后面都在空转
drinker_linux 2010-02-04
  • 打赏
  • 举报
回复
大家请看,我写了两个线程程序,一个写,一个读,已经运行了20分钟了,还没有出任何问题,为什么?

1 #include <stdio.h>
2 #include <pthread.h>
3 #include <queue>
4
5 using namespace std;
6
7 queue<int> qqq;
8 pthread_t pt1,pt2;
9
10 void *thread1(void *arg)
11 {
12 static int num = 0;
13 while(true)
14 {
15 if(qqq.size()>1000)
16 continue;
17 printf("thread1 push num=%d\n",num);
18 qqq.push(num++);
19 if(num >0x0FFFFFFF)
20 num = 0;
21 }
22 }
23
24 void *thread2(void *arg)
25 {
26 int num = 0;
27 while(true)
28 {
29 if(qqq.empty())
30 continue;
31 num = qqq.front();
32 qqq.pop();
33 printf("thread2 pop num=%d\n",num);
34 }
35 }
36
37
38 int main()
39 {
40 pthread_create(&pt1,NULL,thread1,NULL);
41 pthread_create(&pt2,NULL,thread2,NULL);
42 pthread_join(pt1,NULL);
43 pthread_join(pt2,NULL);
44 return 0;
45 }
yshuise 2010-02-04
  • 打赏
  • 举报
回复
queue不加锁的效率都比较低。
jackyjkchen 2010-02-04
  • 打赏
  • 举报
回复
STL的队列算是最简单的设计了,许多库里都有自己的队列,ACE连线程库都有,但它的队列同样没有内部锁,可见队列搞内部线程安全是划不来的
yshuise 2010-02-04
  • 打赏
  • 举报
回复
现在是多核时代了,我想对象大量的数据操作,是很意义的。
yshuise 2010-02-04
  • 打赏
  • 举报
回复
对于13楼的兄弟,我刚才忘说了,我说的队列是先进先出队列
===========
队列还有其它方式?
jackyjkchen 2010-02-04
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 drinker_linux 的回复:]
那么请问能自己实现一个不用加锁即可实现线程安全的队列吗?
[/Quote]
当然可以,意义不大,所有改变队列状态的操作都加锁,就可以保证队列不被破坏,但是效率会下降,而且某些时候仍然需要同步……
traceless 2010-02-04
  • 打赏
  • 举报
回复
这个“锁”在lZ这是个什么概念。。。
yshuise 2010-02-04
  • 打赏
  • 举报
回复
那么请问能自己实现一个不用加锁即可实现线程安全的队列吗?
==============
多线程我还是初学者,不清楚。
drinker_linux 2010-02-04
  • 打赏
  • 举报
回复
对于13楼的兄弟,我刚才忘说了,我说的队列是先进先出队列
加载更多回复(14)

64,637

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

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