事件实现线程同步

1、线程函数声明

DWORD WINAPI ThreadProc(
LPVOID lpParameter);

 2、创建线程函数

HANDLE CreateThread(
LPSECURITY_ATTRIBUTES lpThreadAttributes, 
DWORD dwStackSize, 
LPTHREAD_START_ROUTINE lpStartAddress, 
LPVOID lpParameter, 
DWORD dwCreationFlags, 
LPDWORD lpThreadId); 
lpThreadAttributes:它被设为NULL,表示使用缺省值。 
dwStackSize,线程堆栈大小,一般=0,在任何情况下,
Windows根据需要动态延长堆栈的大小。 
lpStartAddress,指向线程函数的指针,
形式:@函数名,函数名称没有限制,
但是必须以下列形式声明: DWORD WINAPI ThreadProc (LPVOID pParam) ,
格式不正确将无法调用成功。
 lpParameter:向线程函数传递的参数,是一个指向结构的指针,
不需传递参数时,为NULL。 
dwCreationFlags :线程标志,可取值如下  
               CREATE_SUSPENDED: 创建一个挂起的线程 
               0 :创建后立即激活。 lpThreadId:保存新线程的id。   
返回值:   函数成功,返回线程句柄;函数失败返回false。 
3、创建事件对象
 HANDLE CreateEvent(   
   LPSECURITY_ATTRIBUTES lpEventAttributes, // 安全属性  
 BOOL bManualReset, // 复位方式   
   BOOL bInitialState, // 初始状态  
 LPCTSTR lpName // 对象名称   );
lpEventAttributes: 如果lpEventAttributes是NULL,事件将获得一个默认的安全符。  
bManualReset: 指定将事件对象创建成手动复原还是自动复原。如果是TRUE,那么必须用ResetEvent函数来手工将事件的状态复原到无信号状态。如果设置为FALSE,当事件被一个等待线程释放以后,系统将会自动将事件状态复原为无信号状态。
bInitialState: 指定事件对象的初始状态。如果为TRUE,初始状态为有信号状态;否则为无信号状态。  
lpName: 指定事件的对象的名称,是一个以0结束的字符串指针。名称的字符格式限定在MAX_PATH之内。名字是对大小写敏感的。

 

4、WaitForSingleObject函数 

  DWORD WaitForSingleObject(

 

  HANDLE hHandle,

 

  DWORD dwMilliseconds

 

  );

 

参数

  hHandle 对象句柄。可以指定一系列的对象,如Event、Job、Memory resource notification、Mutex、Process、Semaphore、Thread、Waitable timer等。

 

  当等待仍在挂起状态时,句柄被关闭,那么函数行为是未定义的。该句柄必须具有 SYNCHRONIZE 访问权限。

 

  dwMilliseconds [in]定时时间间隔,单位为milliseconds(毫秒).如果指定一个非零值,函数处于等待状态直到hHandle 标记的对象被触发,或者时间到了。如果dwMilliseconds 为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds 为INFINITE,对象被触发信号后,函数才会返回。

返回值

  执行成功,返回值指示出引发函数返回的事件。它可能为以下值:

 

  

 

  WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

 

  返回值:

 

 

  WAIT_ABANDONED 0x00000080:当hHandle为mutex时,如果拥有mutex的线程在结束时没有释放核心对象会引发此返回值。

 

  WAIT_OBJECT_0 0x00000000 :核心对象已被激活

 

  WAIT_TIMEOUT 0x00000102:等待超时

 

  WAIT_FAILED 0xFFFFFFFF :出现错误,可通过GetLastError得到错误代码

 

  在这里举个例子:

 

  先创建一个全局Event对象g_event:

 

  CEvent g_event;

 

  在程序中可以通过调用CEvent::SetEvent设置事件为有信号状态。

 

  下面是一个线程函数MyThreadPro()

 

  UINT CFlushDlg::MyThreadProc( LPVOID pParam )

 

  {

 

  WaitForSingleObject(g_event,INFINITE);

 

  For(;;)

 

  {

 

  ………….

 

  }

 

  return 0;

 

  }

 

  在这个线程函数中只有设置g_event为有信号状态时才执行下面的for循环,因为g_event是全局变量,所以我们可以在别的线程中通过g_event. SetEvent控制这个线程。

 

  还有一种用法就是我们可以通过WaitForSingleObject函数来间隔的执行一个线程函数的函数体

 

  UINT CFlushDlg::MyThreadProc( LPVOID pParam )

 

  {

 

  while(WaitForSingleObject(g_event,MT_INTERVAL)!=WAIT_OBJECT_0)

 

  {

 

  ………………

 

  }

 

  return 0;

 

  }

 

  在这个线程函数中可以通过设置MT_INTERVAL来控制这个线程的函数体多久执行一次,当事件为无信号状态时函数体隔MT_INTERVAL执行一次,当设置事件为有信号状态时,线程就执行完毕了。

 

5实例分析

#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;

 

//创建事件,NULL默认安全性;FALSE自动重置事件对象,当线程等到该事件的所有权后,系统自动将该对象设为无信号状态;TRUE初始有信号;NULL无名事件

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

 hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);//创建线程
 hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);
   
 CloseHandle(hThread1);//关闭线程
 CloseHandle(hThread2);

 

 Sleep(4000);//延时4s

 

 CloseHandle(g_hEvent);//关闭事件
}

 

//线程函数实现

DWORD WINAPI Fun1Proc(
LPVOID lpParameter)
{
 while(TRUE)
 {
  WaitForSingleObject(g_hEvent,INFINITE);//等待事件

  if(tickets>0)
  {
   Sleep(1);
   cout<<"thread1 sell ticket : "<<tickets--<<endl;
   SetEvent(g_hEvent);//设置事件有信号
  }
  else
  {
   SetEvent(g_hEvent);
   break;
  }
 }
 return 0;
}

DWORD WINAPI Fun2Proc(
LPVOID lpParameter)
{
 while(TRUE)
 {
  WaitForSingleObject(g_hEvent,INFINITE);

  if(tickets>0)
  {
   Sleep(1);
   cout<<"thread2 sell ticket : "<<tickets--<<endl;
   SetEvent(g_hEvent);
  }
  else
  {
   SetEvent(g_hEvent);
   break;
  }
 }
 return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ANTRK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值