MFC多线程同步类的使用

上传人:壹****1 文档编号:430853463 上传时间:2024-03-02 格式:DOC 页数:2 大小:232KB
返回 下载 相关 举报
MFC多线程同步类的使用_第1页
第1页 / 共2页
MFC多线程同步类的使用_第2页
第2页 / 共2页
亲,该文档总共2页,全部预览完了,如果喜欢就下载吧!
资源描述

《MFC多线程同步类的使用》由会员分享,可在线阅读,更多相关《MFC多线程同步类的使用(2页珍藏版)》请在金锄头文库上搜索。

1、1. 线程基本知识一个单独执行的程序缺省地包含一个主线程, 主线程以函 数地址的形式出现, 提供程序的启动点, 如 main( ) 或 WinMain( )函数等。当主线程终止时, 进程也随之终止。根据实际需要, 应用程序可以分解成许多独立执行的线程, 每个线程并行的运行在 同一进程中。可以这样理解线程, 它是进程内部一个独立的执行单元, 相 当于一个子程序。一个进程的所有线程都在该进程的虚拟地址 空间中, 使用该进程的全局变量和系统资源, 诸如打开的文件、 信号标识及动态分配的内存等。但同时每个线程可以拥有自己的变量, 诸如独立的堆栈和 CPU 寄存器状态。操作系统给每个 线程分配不同的 C

2、PU 时间片, 多个时间片中的线程在 CPU 内轮流执行。由于每个时间片很短, 所以在用户看来, 好像各线程是并行处理的。多线程使性能增强, 容量增大, 用户响应更快速。用进程和 线程的观点来研究软件是当今普遍采用的方法, 对提高软件的 并行性也有重要意义。现在的大型应用软件无一不是多线程多 任务处理, 单线程的软件是不可想象的。因此掌握多线程多任务 设计方法对每个程序员都是必不可少的。本文针对多线程技术 在应用中经常遇到的同步问题进行探讨。MFC 是微软的 VC 开发集成环境中提供给程序员的基础函 数库, 它用类库的方式将 Win32 API( Win32 API 是 Windows 操作系

3、统内核与应用程序之间的界面, 它把内核提供的功能包装成函数, 其中也包括一些处理多线程的函数集。) 进行封装, 以类 的方式提供给开发者。它有快速、简捷、功能强大等特点。在象( CSyncObject、CSemaphore、CMutex、CCriticalSection 和 CEvent) 和同步访问对象( CMultiLock 和 CSingleLock) 。那么到底在何时使用何种同步对象和同步访问对象呢? 在MSDN 中有如下提示:如果应用程序必须等到发生某事才能访问资源( 例如, 在将数 据 写 入 文 件 之 前 , 必 须 先 从 通 信 端 口 接 收 它 ) ,CEvent。则

4、使 用如果同一应用程序内一个以上的线程可以同时访问此资源( 例如, 应用程序允许在同一文档上最多同时打开五个带有视图的窗口) ,则使用 CSemaphore。如果可以有一个以上的应用程序使用此资源( 例如, 资源在DLL 中) , 则使用 CMutex。如果不是以上情况的同步则使用 CCriticalSection。但是从不直接使用 CSyncObject。它是其他四个同步类的基 类。下面讨论同步对象和同步访问对象的具体使用。2.1 临界区临 界 区 通 过 对 多 线 程 的 串 行 化 来 访 问 公 共 资 源 或 一 段 代码, 可以保证在某一确定时间只有一个线程访问共享数据, 且速

5、度快。使用它时, 各个线程必须要有一个共享的临界区 Ccriti- calSection 对象。无论哪个线程占有临界区对象, 都要调用临界 区对象的 Lock()成员函数, 将共享数据锁定。这时候其它线程不 能访问被锁定数据, 需要等待, 直到调用 Lock()成员函数的线程 再次调用临界区对象的 Unlock()成员函数, 释放对临界区对象的 拥有权为止。临界区被释放后, 其他线程可以强占这个临界区。 因为临界区对象使用比较简单, 在这里就不再举例。2.2 互斥量:互 斥 量 是 为 协 调 共 同 对 一 个 共 享 资 源 的 单 独 访 问 而 设 计的。互斥与临界区很相似, 但是使用

6、时相对复杂一些, 它不仅可MFC 类库中, 提供 了 对 多 线 程 编 程 的 支 持 ,基 本 原 理 与 基 于Win32 API 的设计一致, 但由于 MFC 对同步对象做了封装, 因此实现起来更加方便, 避免了对象句柄管理上的烦琐工作。因 此, 本文使用 MFC 类库进行实例设计。2. MFC 同步类和同步访问类的使用在线程体内, 如果该线程完全独立, 与其它线程没有数据存 取等资源操作上的冲突, 则可按照通常单线程的方法进行编程。 但是, 在多线程处理时这种情况几乎是很少见的。线程之间经常 要进行同步资源访问。如果设计不合理, 两个或多个线程同时访 问同一数据会导致不可预知的结果。

7、例如, 一个线程可能正在更新数组的内容, 而另一个线程正在读取同一数组的内容。这时读取线程收到的是旧数据, 还是新写入的数据或两种数据都有, 将 是不可预测的。与此类似的资源共享问题在多线程编程中是不 可避免的。需要着重指出的是典型的多线程应用程序应具有代 表各个线程间要共享的资源的类。正确设计的完全线程安全类不需要调用任何同步函数。该类的任何事情都在内部处理, 使您 可以将精力集中于如何更好地使用类, 而不是它如何会损坏。创 建完全线程安全类的最佳技术是将同步类合并到资源类中。为以在同一应用程序的线程间实现同步,还可以在不同的进程间实现同步, 从而实现资源的安全共享。使用互斥对象时, 必须先

8、创建一个 Cmutex 对象, 然后再创建一个 CSingleLock 或 CMulti- Lock 对象用于实际的访问控制( 对于单个互斥使用 CSingleLock 对象, 否则使用 CMultiLock 对象) 。 利用访问控制对象的 Lock ()函数可以占有互斥, 而 Unlock()可以释放互斥。为了说明互斥 量的使用, 我编写了一个简单的例子。在本例中有两个线程, 一 个诊室 看 病 记 录 线 程 ( CDisplayThread) 和 一 个 诊 室 病 员 计 数 线程( CCounterThread) 。 这 两 个 线 程 同 时 操 作 一 个 字 符 串 变 量m_

9、strNumber, 其中诊室看病记录线程不断读取该字符串作为当前病员号, 而诊室病员计数线程则将该字符串中的整数加 1, 提 示新的病员申请就诊。程序分别调整进程、两线程的优先级。同步机制使用 CMutex 和 CSingleLock 来保证两个线程不能同时访 问该字符串。图 1 是两线程同步的执行情况。了解决这种线程同步问题,MFC 提供了六种多线程类:同步对CString m_strNumber;/线程所要操作的资源对象CSemaphore* m_semaphore;/用于同步机制的信号量CWinThread* m_pCounterThread;/ 指向第 1 诊室看病记录线程的指针 C

10、WinThread* m_pDisplayThread;/指向诊室病员计数线程的指针 CWinThread* m_pAddThread;/ 指向第 2 诊室看病记录线程的指针/在 *Dlg.cpp 文件中声明事件对象static CEvent g_End3;/在:OnInitDialog()中初始化事件对象和信号量g_End0.ResetEvent(); g_End1.ResetEvent(); g_End2.ResetEvent(); m_semaphore=new CSemaphore(2,2);/控制诊室病员计数线程执行的函数static UINT Run1(LPVOID pParam)

11、;/控制第 1 诊室看病记录线程执行的函数static UINT Run2(LPVOID pParam);控制第 2 诊室看病记录线程执行的函数与控制第 1 诊室看 病记录线程执行的函数基本相同, 就不再列出。2.4 事件图 1以下是本例的部分代码。/在头文件中声明以下变量。CString m_strNumber;/线程所要操作的资源对象CMutex m_mutex;/用于同步机制的互斥量CWinThread* m_pCounterThread;/指向诊室病员计数线程的指针CWinThread* m_pDisplayThread;/指向诊室看病记录线程的指针/控制诊室病员计数线程执行的函数st

12、atic UINT Run1(LPVOID pParam);/控制诊室看病记录线程执行的函数static UINT Run2(LPVOID pParam);2.3 信号量:信号量是为控制一个具有有限数量的用户资源而设计的。事件用来通知线程有一些事件已发生,从而启动后继任务的开始, 或结束现有任务。它是在线程之间传递信号进行通信的一种比较复杂的方法。在使用事件通信前要先创建 Cevent 类的 对象。它始终处于有信号状态或无信号状态。线程可以监视处于 有信号状态的事件, 以便在适当的时候执行对事件的操作。信号量的用法和互斥的用法很相似,不同的是它允许多个线程细心的读者会注意到,我在上例中使用了事

13、件对象以结束在 同 一 时 刻 访 问 同 一 个 资 源 。 在 使 用 时 先 创 建 一 个 信 号 量Csemaphore 对象, 然后创建一个 CsingleLock 或 CmltiLock 对象 实现计数处理。当调用 CsingleLock 或 CmltiLock 对象的 Lock() 函数时, 会减少这个信号量的计数值; 而当调用 Unlock()函数时 则增加这个信号量的计数值。下面我将上例中的诊室看病记录 线程( CDisplayThread) 改为第 1 诊室看病记录线程, 并且增加了 一 个 第 2 诊 室 看 病 记 录 线 程 ( CAddThread) , 原 来

14、的 诊 室 病 员 计 数线程( CCounterThread) 不便, 这样就有三个线程同时操作一个 字 符 串 变 量 m_strNumber。 同 步 机 制 使 用 Csemaphore 和 CSin- gleLock 来保证三个线程中只有两个可以同时访问该字符串。图2 是三线程同步的执行情况。线程。当线程控制函数接到事件信号时, 就会结束当前线程。在:OnStop()函数中事件变为有信号状态。3. 结论:多线程应用程序设计中的一部分工作, 就是要决定在何处存在可能潜在地引起数据毁坏的数据访问冲突,以及如何使用同步来避免这种冲突。如果用户的应用程序需要多个任务同时进行处理, 则使用多线

15、程是较理想的。但线程毕竟是一种系统资 源, 不是无代价的。在创建线程和切换线程时都要增加 CPU 的 额外负担, 所以基于 CPU 的计算在多线程情况下不可能比在单 线程情况下执行地更快。建议您在多线程确实能够给您的应用 程序设计带来好处时才使用它们。参考文献:1. MSDN Library2.东方人华主编 Visual C+ + 6.0 范例入门与提高清华大学出版社3. 刘涛 编著 VC 中利用多线程技术实现线程之间的通信 网址 http:/ / 4. 辛长安 编著 VC + + 编程技术与难点剖析清华大学出版社 出版日 期 2002 年 4 月 1 日5. 孙鑫编著VC+ + 深入详解电子工业出版社出版日期 2006- 6- 16. 揣锦华编著面向对象程序设计与 VC + + 实践西安电子科技大学出版社出版日期 2005- 2- 1图 2以下是本例的部分代码。在头文件中声明以下变量。7. R .ALEXAN DER 编著王峰 翻译深入 C+ + 系列- C + + 高效编程:内存与性能优化

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 大杂烩/其它

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号