一、用CEvent实现线程同步

事件对象(Event)是最简单的同步对象,它包括有信号和无信号两种状态。在线程访问某一资源之前,也许需要等待某一事件的发生,这时用事件对象最合适。例如,只有在通信端口缓冲区收到数据后,监视线程才被激活。MFC中,CEvent类提供了对事件的支持。CEvent对象有两种类型:人工事件和自动事件。对于自动事件,当其获得信号后,就会释放下一个可用的线程。一个自动CEvent对象在被至少一个线程释放后会自动返回到无信号状态;而人工事件对象获得信号后,释放所有可利用线程,直到调用成员函数ReSetEvent()将其设置为无信号状态时为止。

在创建CEvent对象时,默认创建的是自动事件

CEvent类的构造函数原型如下:
CEvent(BOOL bInitia11y0wn=FALSE,//若bInitiallyOwn为TRUE,则使CMultilock类对象和CSingleLock类对象的线程可用;否则,要访问资源的线程必须等待。该参数的默认值为FALSEo

BOOL bManualReset = FALSE,//指定要创建的CEvent对象是属于手工事件还是自动事件。为TRUE,则为手工事件;否则为自动事件。该参数默认值为FALSE o

LPCTSTR lpszName=NULL,//指定要创建的事件对象的名,如果该事件对象将跨进程使用,则此参数不能为NULL。如果该参数和一个已经存在的CEvent对象相同,则该构造函数返回一个对这个已存在对象的引用;如果参数和一个已存在的非CEvent类的同步对象(如CMutex )相同,则对象创建失败。

LPSECURITY ATTRIBUTES lpsaAttribute=NULL)//指定要创建对象的安全属性,一般置为NULL o

在事件对象建成后,可以调用其成员函数来改变其状态。CEvent类的几个重要的成员函数

SetEvent:将CEvent类对象的状态设置为有信号状态,并且释放所有等待的线程;如果该事件是人工事件,则CEvent类对象保持为有信号状态,直到调用成员函数ResetEvent将其重新设为无信号状态时为止,这样该事件就可以释放多个线程;如果CEvent类对象为自动事件,则在SetEvent将事件设置为有信号状态后,CEvent类对象由系统自动重置为无信号状态,除非一个线程被释放

ResetEvent:该函数将事件的状态设置为无信号状态,并保持该状态直至SetEvent被调用时为止。由于自动事件是由系统自动重置,故自动事件不需要调用该函数

PulseEnent:发送一个事件脉冲,该函数完成一系列操作后才返回。对于自动事件,PulseEvent将事件设置为有信号状态,等待一个线程被释放,将事件重置为无信号状态,然后PulseEvent返回;对于人工事件,则将等待该事件的所有线程被释放,事件被自动重置为无信号状态,然后PulseEvent返回

一个CEvent对象在线程中被创建后,自动处于无信号状态,但在另一个线程中可以调用API函数WaitForSingleObject来监视其状态

二、CCriticalSection类实现线程同步

当多个线程访问一个独占性共享资源时,可以使用Critical Section(临界区)对象。任一时刻只有一个线程可以拥有临界区对象,拥有临界区的线程可以访问被保护起来的资源或代码段,其他希望进入临界区的线程将被挂起等待,直到拥有临界区的线程放弃临界区时为止。因此,任一时刻,只有一个线程可以拥有临界区对象,而只有拥有临界区对象的线程才可以访问受保护的数据。

MFC的CCriticalSection类提供了对临界区对象的支持,其用法也相当简单,有两种用法。

1.单独使用CCriticalSection对象

1)定义CCriticalSection类的一个全局对象,以使各个线程均能访问,例如:CCriticalSection criticalsection;//CCriticalSection类的构造函数只有一种形式,即不带任何参数

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

如果此时没有其他线程占有临界区对象,则调用Lock函数的线程获得临界区;否则,线程即将挂起,并放人到一个系统队列中等待,直到当前拥有临界区的线程释放了临界区时为止。

3)访问临界区完毕后,使用CCriticalSection的成员函数Unlock来释放临界区。代码如下:critical section.Unlock()

2.与同步辅助类CSingleLock或CMutiLock一起使用

下面以类CSingleLock为例,简单说明使用步骤:

1)定义CCriticalSection类的一个全局对象,格式如下:CCriticalSection critical_section;

2)在访问需要保护的资源之前,定义CSingleLock类的一个变量,并将critical_ section的地址传送给构造函数:CSingleLock singlelock(&critical_ section):

3)使用CSingleLock类的成员函数LOCk请求获得临界区。代码如下:singlelock.Lock();如果临界区已经被其他线程占用,则本线程挂起,等待临界区被释放。获得临界区对象后返回。

4)本线程中访问临界区中的共享资源后,调用CSingleLock类的成员函数Unlock来释放临界区:singlelock.Unlock();

三、CSemaphore类实现线程同步

使用信号量对象(Semaphore)也可以实现线程同步。信号量对象维护一个从0开始的计数,在计数值大于0时对象是有信号的,而在计数值为0时则是无信号的。通过使用信号量对象,可以限制对共享资源进行访问的线程数量。MFC中,CSemaphore类实现了对信号量对象的封装。具体来讲,CSemaphore的一个对象保存了对当前访问某一指定资源的线程的计数值,该计数值是当前还可以使用该资源的线程的数目。如果这个计数达到了零,则所有对这个CSemaphore类对象所控制的资源的访问尝试都被放入到一个队列中等待,直到超时或计数值不为零时为止。当一个线程访问了被保护的资源时,计数值减1;一个线程完成了对被控共享资源的访问时,计数值增to在CSemaphore类对象的构造函数中可以指定控制的资源可以同时接受访问的最大线程数,

构造函数原型如下。

CSemaphore
(LONG lInitialCount=1,//信号量对象的初始计数值,决定了在信号量对象建成后,能同时访问其中资源的最大线程数目。必须不小于0,不大于lMaxCount
LONG lMaxCount=1,//信号量对象计数值的最大值,该参数决定了同一时刻可访问由信号量保护的资源的线程最大数目
LPCTSTR pstrName=NULL,//指向要创建的信号量名字。如果该信号量跨进程使用,则该参数不能为空
LPSECURITY_ATTRIBUTES lpsaAttributes=NULL);

CSemaphore类一般也与线程同步辅助类CSingleLock或CMutiLock类结合使用。用法与CCriticalSection类似

CEvent,CSemaphore,CCriticalSection,CMutex的更多相关文章

  1. C++ 系列:多线程编程基础知识

    Copyright © 1900-2016, NORYES, All Rights Reserved. http://www.cnblogs.com/noryes/ 欢迎转载,请保留此版权声明. -- ...

  2. Windows多线程多任务设计初步(转)

    Windows多线程多任务设计初步 [前言:]当前流行的Windows操作系统,它能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程 ...

  3. VC中利用多线程技术实现线程之间的通信

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  4. MFC多线程

    当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软 ...

  5. 【C++】线程_beginthreadex参数说明

    unsigned long _beginthreadex( void * _Security, //第1个参数:安全属性,NULL为默认安全属性 unsigned _StackSize, //第2个参 ...

  6. MFC【17-2】线程和线程同步化

    17-2线程同步 Windows支持4中类型的同步对象,可以用过来同步由并发运行的线程执行的操作: 临界区 互斥量 事件 信号量 MFC在名为CCriticalSection\CMutex\CEven ...

  7. MFC 结束线程

    在wtl工程中定义一个现成,如下:DWORD WINAPI ThreadFunc( LPVOID pParam ){if( g_pMainlg )g_pMainlg->DoEnumNetwork ...

  8. 如何创建一个简单的C++同步锁框架(译)

    翻译自codeproject上面的一篇文章,题目是:如何创建一个简单的c++同步锁框架 目录 介绍 背景 临界区 & 互斥 & 信号 临界区 互斥 信号 更多信息 建立锁框架的目的 B ...

  9. CMutex、CCriticalSection、CSemaphore、CEvent、WaitForSingleObject 的小例子

    一.CMutex CMutex mutex; mutex.Lock(); // 互斥的动作 // mutex.Unlock(); 二.CCriticalSection CCriticalSection ...

随机推荐

  1. STM32F407VG (三)ADC

    12位ADC是一种逐次逼近型模拟数字转换器. 它有多达19个通道,可測量16个外部和2个内部信号源和VBAT通道.各通道的A/D转换能够单次.连续.扫描或间断模式运行. ADC的结果能够左对齐或右对齐 ...

  2. Android解析中国天气网的Json数据

    在Android开发中.一般的APP都是通过获取server端的数据来更新UI.从server获取到的数据能够是Json.它的数据量要比XML要小,这里解析中国天气网上获取的数据,尽管已经不再更新了. ...

  3. 从linux telnet到exchange邮件server来測试发送邮件

    我们在Linux下,能够通过telnet邮件server的25port(一般smtp邮件server都是这个),来測试是否能发送邮件. 前提是先得把DNS配好,或者/etc/hosts文件制定好邮件s ...

  4. Performing a full database disaster recovery with RMAN

    Performing a full database disaster recovery with RMAN1. Make the RMAN backup set pieces available.2 ...

  5. SOA架构有基本的要求

    SOA在相对较粗的粒度上对应用服务或业务模块进行封装与重用: 服务间保持松散耦合,基于开放的标准, 服务的接口描述与具体实现无关: 灵活的架构 -服务的实现细节,服务的位置乃至服务请求的底层协议都应该 ...

  6. IOS开发 统计XCODE 代码行数

    如果要统计ios开发代码,包括头文件的,终端命令进入项目目录下,命令如下 find . -name "*.m" -or -name "*.h" -or -nam ...

  7. c++到c#数据类型的转换

    c++与c#的类型转换 分类:cSharp | 标签: c#  system  intptr  char  uint  2012-02-29 19:54 阅读(513)评论(0)编辑删除 //c++: ...

  8. javascript 手机号抽奖

     案例   ----           手机号抽奖   开始抽奖  停止                                                       *具体的备注在代 ...

  9. 使用CRT定位内存泄漏

    1. 使能内存泄漏检测#define _CRTDBG_MAP_ALLOC#include <stdlib.h>#include <crtdbg.h>注1:语句顺序不能修改:注2 ...

  10. Android 添加菜单项

    刚开始看郭大神的<>,实现以下里面的一些例子.利用Menu给APP添加一个菜单项. 效果图 结构图 在res的menu文件夹下创建一个xml文件,当然你也可以使用系统创建的main.xml ...