首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ Builder >

双CPU,多线程同步有关问题,请进

2012-10-15 
双CPU,多线程同步问题,大虾请进!当我们使用内核对象(如事件内核对象)进行2线程同步的时候,是否会发生如下

双CPU,多线程同步问题,大虾请进!
当我们使用内核对象(如事件内核对象)进行2线程同步的时候,是否会发生如下情况:
两个线程都是第一次启动时候,同时获取到内核对象的使用权?我觉得会发生,上代码:
[code=C/C++][/code]
#include <windows.h>
#include <iostream.h>

DWORD WINAPI Fun1Proc(LPVOID lpParameter);
DWORD WINAPI Fun2Proc(LPVOID lpParameter);

int tickets=100;
HANDLE g_hEvent;
void main()
{
  HANDLE hThread1;
  HANDLE 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);
}


DWORD WINAPI Fun1Proc(
  LPVOID lpParameter
)
{


while(TRUE)
{ //Sleep(10); 不加此行代码时候,结果经常会出现 :
//thread2 sell ticket 100
//thread1 sell ticket 99
WaitForSingleObject(g_hEvent,INFINITE);
 
if(tickets>0)
{ Sleep(1);
cout<<"thread1 sell ticket :"<<tickets--<<endl;

}
else
break;

}

return 0;
}



DWORD WINAPI Fun2Proc(
  LPVOID lpParameter
)
{  
while(TRUE)
{ WaitForSingleObject(g_hEvent,INFINITE);
 
if(tickets>0)
{
cout<<"thread2 sell ticket :"<<tickets--<<endl;


}
else
break;


}

return 0;
}

 结果有两种:
1) thread2 sell ticket :100

2) thread2 sell ticket :100
  thread1 sell ticket :99

按照我的分析,出现结果2的原因为:因我的电脑是双CPU的,所以第一次两个线程可能同时都得到事件内核对象处于信号状态,于是两个线程都获取到了对WaitForSingleObject函数一下的代码的使用权,但是由于线程1的Sleep(1)的存在,所以线程2先完成了cout<<"thread2 sell ticket :"<<tickets--<<endl;这行代码的执行.所以线程2打印100,之后线程1睡眠过后,接着执行cout<<"thread1 sell ticket :"<<tickets--<<endl;这行代码.(因为是自动重置,所以内核对象会一直处于没信号状态,两个线程都不能接着打印!)

 不知道我的分析对不对呢?我想问的是,在双CPU情况下,两个线程是否有可能都同时获取到信号?


[解决办法]
我给你分析一下

首先,你的两个子线程是非挂起创建,创建后两线程就开始执行了,
创建后os对你的进程至少3个线程开始调度,而你的Event对象这个时候还不知道在哪里,
WaitForSingleObject也没判断返回值,那么,会发生什么?
好吧,在你的event事件对象创建之前你线程中的WaitForSingleObject函数会返回失败,
当然,在你这代码里就是继续往下走并继续循环,输出内容,这个过程持续的你的event对象创建完成,
这个过程时间取决于硬件配置,速度,系统调度规则等等,
很显然,这个过程产生的输出是不可预调的

其次,我们再看你的事件对象的创建。你创建的是非管理重置,初始状态为无信号状态的event object, 
所以,在前面说的那个过程结束,你的对象创建后,两线程会开始等待事件信号,直到你的SetEvent(g_hEvent)执行完成,此时,其中一个幸运的子线程将会得到事件信号,由于你的事件是非管理重置,你的event对象自动重置为无信号状态,该线程继续输出相关内容然后继续等待。当然,事件现在处于无信号状态,而你的程序再也没用SetEvent的调用发生,所以,直到你程序结束,再也没人能等到你的event信号了。

从上可知,你程序现在的结果是: 一系列不可预料的输出(包括可能什么都没有) + 某个幸运线程的一条输出 = 不可预料的输出


改下面两个步骤,你应该可以看到想要的结果, 至于为什么,说了那么多,应该可以想明白了
1.把
g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);
放到
hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);
这一行前面

2. 在你两个线程循环中的break; 后面都加一行 SetEvent(g_hEvent);


你这问题是关于事件对象的,我就只说他们相关的,其他问题我就不说了

热点排行