vc++深入详解中的多线程例子,在多核CPU下出错分析。

lph110 2012-01-03 11:15:59

#include <WINDOWS.H>
#include <IOSTREAM>
using namespace std;
/*
* 在单核单CPU下正常运行
*/
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets = 100;
HANDLE g_hEvent;
void main()
{
HANDLE hThread1,hThread2;
hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
SetEvent(g_hEvent);

Sleep(4000);
CloseHandle(g_hEvent);
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"Thread1 sell ticket:"<<tickets--<<endl;
}
else
break;
SetEvent(g_hEvent);
}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"Thread2 sell ticket:"<<tickets--<<endl;
}
else
break;
SetEvent(g_hEvent);
}
return 0;
}

在多核cpu下运行结果出错。执行结果如下:


Thread1 sell ticTkherte:ad120 0s
ell ticket:99
Thread1 sell tickTehtr:e9a8d
2 sell ticket:97
Thread1 sell tickeTth:r9e6a
d2 sell ticket:95
Thread1 sell ticket:94
Thread2 sell tickeTth:r93e
ad1 sell ticket:92
Thread2 sell tickTehtr:e9a1d
1 sell ticket:90
Thread2 sell ticket:8T9
hread1 sell ticket:88
Thread2 sell tickTehtr:e8a7d
1 sell ticket:86
Thread2 sell tickTehtr:e8a5d1
sell ticket:84
TThhrreeaadd12 sseellll ttiicckkeett::8832

TThhrreeada1d 2s eslell lt iticckkeett::8810

TThhreraeda1d 2s eslell lt itcikcekte:t7:97
8
TThhrreeaadd12 sseellll ttiicckkeett::7776

Thread1 sell tickeTth:r7e5a
d2 sell ticket:74
Thread1 sell ticket:73
Thread2 sell ticket:72
Thread1 sell tickeTth:r7e1a
d2 sell ticket:70
Thread1 sell ticket:69
Thread2 sell ticket:68
Thread1 sell tickeTth:r6e7a
d2 sell ticket:66
Thread1 sell ticket:65
Thread2 sell ticket:64
Thread1 sellT htriecakd2e ts:e6l3l
ticket:62
TThhrreeaadd12 sseellll ttiicckkeett::6610

Thread1 sell tickTehtr:e5a9d
2 sell ticket:58
Thread1 sell ticket:57
Thread2 sell ticket:56
Thread1 sell ticket:55
Thread2 sell ticketT:h5r4
ead1 sell ticket:53
Thread2 sell ticket:52
Thread1 sell tickeTth:r5e1a
d2 sell ticket:50
Thread1 sell ticket:49
Thread2 sell ticket:48
Thread1 sell ticket:47
Thread2 sell ticket:46T
hread1 sell ticket:45
Thread2 sell tickTehtr:e4a4d
1 sell ticket:43
Thread2 sell ticket:42
Thread1 sell tickTehtr:e4a1d
2 sell ticket:40
Thread1 sell ticket:39
Thread2 sell ticket:38
Thread1 sell ticketT:h3r7e
ad2 sell ticket:36
Thread1 sell ticket:35
Thread2 sell tickTehtr:e3a4d
1 sell ticket:33
Thread2 sell tickTehtr:e3a2d
1 sell ticket:31
Thread2 sell ticket:30
Thread1 sell ticket:29
Thread2 sell ticket:28
Thread1 sell ticket:27
Thread2 sell tickeTth:r2e6a
d1 sell ticket:25
Thread2 sell ticket:24
Thread1 sell ticket:23
Thread2 sell tickTehtr:e2a2d
1 sell ticket:21
Thread2 sell ticket:20
Thread1 sell ticket:19
Thread2 sell ticket:T1h8r
ead1 sell ticket:17
Thread2 sell ticket:16
Thread1 sell tickeTth:r1e5a
d2 sell ticket:14
Thread1 sell ticket:13
Thread2 sell ticket:1T2h
read1 sell ticket:11
Thread2 sell ticket:10
Thread1 sell ticket:9
Thread2 sell ticket:8
Thread1 sell ticket:Th7r
ead2 sell ticket:6
Thread1 sell ticket:5
Thread2 sell ticket:Th4re
ad1 sell ticket:3
Thread2 sell ticket:2
Thread1 sell ticket:Thr1e
ad2 sell ticket:0
Press any key to continue


结果分析,在运行线程时g_hEvent可能未创建。

代码改为如下变正常了。


#include <WINDOWS.H>
#include <IOSTREAM>
using namespace std;
/*
* 在单核单CPU下正常运行
*/
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets = 100;
HANDLE g_hEvent;
void main()
{
g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
SetEvent(g_hEvent);

HANDLE hThread1,hThread2;
hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

//g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
//SetEvent(g_hEvent);

Sleep(4000);
CloseHandle(g_hEvent);
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"Thread1 sell ticket:"<<tickets--<<endl;
}
else
break;
SetEvent(g_hEvent);
}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"Thread2 sell ticket:"<<tickets--<<endl;
}
else
break;
SetEvent(g_hEvent);
}
return 0;
}


经测试正常了。

这个分析对吗



...全文
218 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
taodm 2012-01-03
  • 打赏
  • 举报
回复
楼主用的什么编译器?VC6这个垃圾货?
lph110 2012-01-03
  • 打赏
  • 举报
回复
证实了确实是这个问题。

#include <WINDOWS.H>
#include <IOSTREAM>
using namespace std;
/*
* 在单核单CPU下正常运行
*/
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets = 100;
HANDLE g_hEvent;
void main()
{
//g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
//SetEvent(g_hEvent);

HANDLE hThread1,hThread2;
hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

g_hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
SetEvent(g_hEvent);

Sleep(4000);
CloseHandle(g_hEvent);
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(TRUE)
{

if(WAIT_FAILED ==WaitForSingleObject(g_hEvent,INFINITE))
{
CHAR szBuf[80];
DWORD dw = GetLastError();
sprintf(szBuf,"WaitForSingleObject is fail,ErrorNo. is %u\n",dw);
printf(szBuf);
break;
}
//ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"Thread1 sell ticket:"<<tickets--<<endl;
}
else
break;
SetEvent(g_hEvent);
}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(TRUE)
{
if(WAIT_FAILED ==WaitForSingleObject(g_hEvent,INFINITE))
{
CHAR szBuf[80];
DWORD dw = GetLastError();
sprintf(szBuf,"WaitForSingleObject is fail,ErrorNo. is %u\n",dw);
printf(szBuf);
break;
}
//ResetEvent(g_hEvent);
if (tickets > 0)
{
Sleep(1);
cout<<"Thread2 sell ticket:"<<tickets--<<endl;
}
else
break;
SetEvent(g_hEvent);
}
return 0;
}

lph110 2012-01-03
  • 打赏
  • 举报
回复
代码改成这个。
有时候2个线程都不能运行。


#include <iostream>

#include <windows.h>

using namespace std;
/*
* 在多核单CPU,多核多CPU下正常运行
*/
DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets = 100;
HANDLE g_hEvent;
//CCriticalSection g_clsCriticalSection;

void main()
{
HANDLE hThread1,hThread2;
hThread1 = CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
hThread2 = CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
CloseHandle(hThread1);
CloseHandle(hThread2);

g_hEvent = CreateEvent(NULL,FALSE,TRUE,NULL);
//SetEvent(g_hEvent);
WaitForSingleObject(hThread1,INFINITE);
WaitForSingleObject(hThread2,INFINITE);
Sleep(4000);
//CloseHandle(g_hEvent);
}

DWORD WINAPI Fun1Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
//g_clsCriticalSection.Lock();
if (tickets > 0)
{
Sleep(1);
cout<<"Thread1 sell ticket:"<<tickets--<<endl;
}
else
break;
//g_clsCriticalSection.Unlock();
SetEvent(g_hEvent);
}
return 0;
}

DWORD WINAPI Fun2Proc(LPVOID lpParameter)
{
while(TRUE)
{
WaitForSingleObject(g_hEvent,INFINITE);
//ResetEvent(g_hEvent);
//g_clsCriticalSection.Lock();
if (tickets > 0)
{
Sleep(1);
cout<<"Thread2 sell ticket:"<<tickets--<<endl;
}
else
break;
//g_clsCriticalSection.Unlock();
SetEvent(g_hEvent);
}
return 0;
}


taodm 2012-01-03
  • 打赏
  • 举报
回复
珍惜生命,远离VC6.
不要用它来浪费大家的时间了。
lph110 2012-01-03
  • 打赏
  • 举报
回复
就是vc6 sp6,时不时的老卡死在编译或链接的时候。

64,686

社区成员

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

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