一、用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. mac 安装maven 和改动java环境变量

    一. 首先是安装maven: 步骤: 1.下载Maven tar包 http://maven.apache.org/download.cgi 2. 下载后解压到某个目录下 [html] view pl ...

  2. Java程序员应该知道的10个面向对象理论

    英文原文:10-object-oriented-design-principles 面向对象理论是面向对象编程的核心,但是我发现大部分 Java 程序员热衷于像单例模式.装饰者模式或观察者模式这样的设 ...

  3. Windowsclient开发简单介绍(四)

            在上一篇文章里,我简单扼要的给大家介绍了一下GDI的基础知识,包含DC,HDC.GDI对象等等,总的来说都是些偏理论的知识,属于概念的范畴. 今天这篇文章里,我就要正式開始有点实际的东 ...

  4. SOA架构有基本的要求

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

  5. javascript设计模式——Observer

    定义一种一对多的从属关系,当一个目标状态改变,所有他的从属对对象都将收到通知. 1.简单的Observer模式 实现 var Observer = function(){ this.list = [] ...

  6. UVA 714 Copying Books

    题意: 要抄N本书,编号为1,2,3...N, 每本书有1<=x<=10000000页, 把这些书分配给K个抄写员,要求分配给某个抄写员的那些书的编号必须是连续的.每个抄写员的速度是相同的 ...

  7. (转)C#反射机制详解

    反射的定义:审查元数据并收集关於它的类型信息的能力,元数据(编辑后的基本数据单元)就是一大堆表,编译器会创建一个类定义表,一个字段定义表,一个方法定义表等,System.Reflection命名空间包 ...

  8. HTML 5 JavaScript初步 编译运行.doc

    编译运行 解释运行 JavaScript:只有一种变量类型,var.数据类型:整型,小数,字符串,布尔型 1.如何把数值型字符串变成数字型: parseInt("字符串")——把字 ...

  9. C++<algorithm>中sort的比较函数写法(转)

    转自:http://www.wl566.com/biancheng/98907.html C++<algorithm>中sort的比较函数写法,有需要的朋友可以参考下. 定义排序函数: 方 ...

  10. visual assist常用快捷键

    转自http://my.oschina.net/u/211101/blog/127822 一些打开啊新建就不说了…… //先来个我自己最喜欢的,经常不用,老忘记,以前eclipse最喜欢这个快捷键了 ...