。
---- 同步类用于当访问资源时保证资源的整体性。其中CsyncObject 是其它四个同步类的基类,不直接使用。信号同步类CSemaphore 通常用于当一个应用程序中同时有多个线程访问一个资源(例如,应用程序允许对同一个Document 有多个View)的情况;事件同步类CEvent 通常用于在应用程序访问资源之前应用程序必须等待(比如,在数据写进一个文件之前数据必须从通信端口得到)的情况;而对于互斥同步类CMutex 和临界区同步类CcriticalSection 都是用于保证一个资源一次只能有一个线程访问,二者的不同之处在于前者允许有多个应用
程序使用该资源(例如,该资源在一个DLL 当中)而后者则不允许对同一个资源的访问超出进程的范畴,而且使用临界区的方式效率比较高。
---- 同步访问类用于获得对这些控制资源的访问。CMultiLock 和CSingleLock 的区别仅在于是需要控制访问多个还是单个资源对象。
---- 5 同步类的使用方法
---- 解决同步问题的一个简单的方法就是将同步类融入共享类当中,通常我们把这样的共享类称为线程安全类。下面举例来说明这些同步类的使用方法。比如,一个用以维护一个帐户的连接列表的应用程序。该应用程序允许3 个帐户在不同的窗口中检测,但一次只能更新一个帐户。当一个帐户更新之后,需要将更新的数据通过网络传给一个数据文档。
---- 该例中将使用3 种同步类。由于允许一次检测3 个帐户,使用CSemaphore 来限制对3 个视窗对象的访问。当更新一个帐目时,应用程序使用CCriticalSection 来保证一次只有一个帐目更新。在更新成功之后,发CEvent 信号,该信号释放一个等待接收信号事件的线程。该线程将新数据传给数据文档。
---- 要设计一个线程安全类,首先根据具体情况在类中加入同步类做为数据成员。在例子当中,可以将一个CSemaphore 类的数据成员加入视窗类中,一个CCriticalSection 类数据成员加入连接列表类,而一个CEvent 数据成员加入数据存储类中。
---- 然后,在使用共享资源的函数当中,将同步类与同步访问类的一个锁对象联系起来。即,在访问控制资源的成员函数中应该创建一个CSingleLock 或CMultiLock 的对象并调用该对象的Lock 函数。当访问结束之后,调用UnLock 函数,释放资源。
---- 用这种方式来设计线程安全类比较容易。在保证线程安全的同时,省去了维护同步代码的麻烦,这也正是OOP 的思想。但是使用线程安全类方法编程比不考虑线程安全要复杂,尤其体现在程序调试过程中。而且线程安全编程还会损失一部分效率,比如在单CPU
计算机中多个线程之间的切换会占用一部分资源。
三编程实例
---- 下面以VC++5.0 中一个简单的基于对话框的MFC 例程来说明实现多线程任务调度与处理的方法,下面加以详细解释。
---- 在该例程当中定义两个用户界面线程,一个显示线程(CDisplayThread) 和一个计数线程(CCounterThread)。这两个线程同时操作一个字符串变量m_strNumber,其中显示线程将该字符串在一个列表框中显示,而计数线程则将该字符串中的整数加1。在例程中,可以分别调整进程、计数线程和显示线程的优先级。例程中的同步机制使用CMutex 和CSingleLock 来保证两个线程不能同时访问该字符串。同步机制执行与否将明显影响程序的执行结果。在该例程中允许将将把两个线程暂时挂起,以查看运行结果。例程中还允许查看计数线程的运行。该例程中所处理的问题也是多线程编程中非常具有典型意义的问题。
---- 在该程序执行时主要有三个用于调整优先级的组合框,三个分别用于选择同步机制、显示计数线程运行和挂起线程的复选框以及一个用于显示运行结果的列表框。
---- 在本程序中使用了两个线程类CCounterThread 和CDisplayThread,这两个线程类共同操作定义在CMutexesDlg 中的字符串对象m_strNumber。本程序