线程的同步对象

线程的同步对象

(2010-05-15 20:55:30)
使同一进程的各线程协调一致地工作称为线程的同步。MFC提供了多种同步对象,通过这些类,我们可以比较容易地做到线程同步。最常用的四种:

1、临界区(CCriticalSection)

2、事件(CEvent)

3、互斥量(CMutex)

4、信号量(CSemaphore)

 

一、使用临界区——CCriticalSection类

当多个线程访问一个独占性共享资源时,可以使用“临界区”对象。
CCriticalSection类的用法步骤如下:
1、定义CCriticalSection类的一个全局对象(以使各个线程均能访问),

如CCriticalSection critical_section;

 

2、在访问需要保护的资源或代码之前,调用CCriticalSection类的成员Lock()获得临界区对象: critical_section.Lock(); 

如果此时没有其它线程占有临界区对象,则调用Lock()的线程获得临界区;

否则,线程将被挂起,并放入到一个系统队列中等待,直到当前拥有临界区的线程释放了临界区时为止。

 

3、访问临界区完毕后,使用CCriticalSection的成员函数Unlock()来释放临界区:

critical_section.Unlock();


 

说明它的意义我用一个假设来说明:

有两个线程A、B,它们都声明了临界区对象,以访问被保护起来的资源或代码段。

1、在某一时刻,A 拥有了临界区对象,可以访问被保护起来的资源或代码段;

2、此时 B 若想进入临界区,执行critical_section.Lock();,则它被挂起等待,直A 放弃临界区,即执行完critical_section. Unlock();时为止;

这样就保证了不会在同一时刻出现多个线程访问共享资源。 

 

二、使用事件——CEvent类

事件是一个允许一个线程在某种情况发生时,唤醒另外一个线程的同步对象。

每一个CEvent 对象可以有两种状态:有信号状态和无信号状态。

在MFC中,CEvent 类对象有两种类型:人工事件和自动事件。

 

 CEvent 类的各成员函数的原型和参数说明如下:

1、CEvent(BOOL bInitiallyOwn=FALSE, //指定事件对象初始化状态,TRUE为有信号,FALSE为无信号
          BOOL bManualReset=FALSE,  //TRUE为人工事件,FALSE为自动事件
          LPCTSTR lpszName=NULL,
          LPSECURITY_ATTRIBUTES lpsaAttribute=NULL);

 

2、BOOL CEvent::SetEvent(); //将 CEvent 类对象的状态设置为有信号状态。

1)若事件是人工事件, CEvent 类对象保持为有信号状态,直到调用成员函数ResetEvent()将其重新设为无信号状态时为止。

2)若为自动事件,则在SetEvent()将事件设置为有信号状态后,CEvent 类对象由系统自动重置为无信号状态。
如果该函数执行成功,则返回非零值,否则返回零。

 

3、BOOL CEvent::ResetEvent(); //将事件设置为无信号状态,并保持直至SetEvent()被调用时为止。

自动事件不需要调用该函数。

如果该函数执行成功,返回非零值,否则返回零。

我们一般通过调用WaitForSingleObject函数来监视事件状态。

 

例如:

在某些网络应用程序中,线程 A 负责监听通讯端口,线程 B 负责更新用户数据。通过使用CEvent 类,线程A可以通知线程B何时更新用户数据。

 

三、使用互斥量——CMutex类

互斥对象与临界区对象很像。不同在于:

互斥对象可以在进程间使用,而临界区对象只能在同一进程的各线程间使用。

当然,互斥对象也可以用于同一进程的各个线程间,但如果在这种情况下,使用临界区会更节省系统资源,更有效率。

 

四、使用信号量——CSemaphor类

当需要一个计数器来限制可以使用某个线程的数目时,可以使用“信号量”对象。

 

CSemaphore 类的构造函数原型及参数说明如下:

CSemaphore (

LONG lInitialCount=1, //初始计数值,即可访问线程数目的初始值

LONG lMaxCount=1, //信号量对象计数值的最大值,决定了同一时刻可访问由信号量保护的资源的线程最大数目
LPCTSTR pstrName=NULL,
LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);

 

例子:
假设有无数线程,有一个共享资源,它的最大访问量是N,也就是同一时刻可以访问线程数目lMaxCount是N。

每增加一个线程对共享资源的访问,N 减1,只要 N 是大于0的,就可以发出信号量信号;

如果 N=0了,说明当前占用资源的线程数已经达到了所允许的最大数目,不能再允许其它线程的进入,此时的信号量信号将无法发出,访问尝试都被放入到一个队列中等待,直到超时或 N 不为零时为止。

线程在处理完共享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源数加1。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值