您好,欢迎访问三七文档
当前位置:首页 > 电子/通信 > 综合/其它 > C++_编程_第十七章__线程同步与进程通信
联系方式:北京源智天下科技有限公司第十七讲:线程同步与进程通信杨章伟e-mail:yang505412@163.com1-2北京源智天下科技有限公司联系方式:课程内容安排•进程和线程•MFC的线程处理•线程同步•进程通信•综合练习•思考和习题1-3北京源智天下科技有限公司联系方式:进程和线程•读者在使用32位Windows操作系统如WindowsXP时,能够同时运行几个程序。这种能力称为多任务处理。多任务其实就可以理解为系统可以同时运行多个进程。•进程(Process)是一个运行的程序,其由独立的虚拟内存、代码、文件句柄和其他系统资源组成。简单的说,进程是操作系统分配内存地址空间的基本单位。•线程(Thread)是操作系统分配处理器时间的最小单元。一个进程必须包含一个线程,称之为主线程。进程中的线程是并行执行的。每个线程占用CPU的时间由系统来划分。1-4北京源智天下科技有限公司联系方式:•假如有一个公司,公司里有很多各司其职的职员。那么读者可以认为这个正常运作的公司就是一个进程,而公司里的职员就是线程。一个公司至少得有一个职员。同理,一个进程至少包含一个线程。在公司里,一个职员可以干所有的事,但是效率很显然不会很高,这就需要引入多线程了。一个公司(进程)中包含多个各负其责的职员(线程),如图17-1所示。1-5北京源智天下科技有限公司联系方式:的线程处理总的来说,Win32API提供的线程处理的接口,但其引用较为复杂。因此,在Win32API的基础上,MFC提供了处理线程的类和函数。其中,MFC提供处理线程的类为CWinThread类。CWinThread类使用线程本地存储来管理在MFC环境中的线程的上下文信息。1-6北京源智天下科技有限公司联系方式:一般的说,用户可以直接声明CWinThread对象,但在许多情况下,可以让MFC的全局函数AfxBeginThread()来创建CWinThread对象。CWinThread类提供了几个函数来对线程进行操作。例如:CWinThread::AfxBeginThread()函数:用来创建进程。CWinThread::CreateThread()函数:用来启动新的线程。CWinThread::SuspendThread()函数:用来挂起线程。CWinThread::ResumeThread()函数:用来恢复线程的执行。MFC中支持两种类型的线程:工作者线程和用户界面线程。其区别在于:工作者线程常用于完成不要求用户输入的任务,如耗时计算、后台打印之类的任务。因此,其不需要有界面。1-7北京源智天下科技有限公司联系方式:创建工作者线程工作者线程可以说是并行执行的一个函数,其一般用来完成那些不需要用户输入的后台任务。例如数据库备份功能和网络联接状态监视等功能。简单的说,创建一个工作者线程就是实现一个控制函数,并将其地址传给适当的形式的AfxBeginThread()函数的问题。一般的说,工作者线程形式的AfxBeginThread()的声明的格式如下:CWinThread*AFXAPIAfxBeginThread(AFX_THREADPROCpfnThreadProc,LPVOIDpParam,intnPriority,UINTnStackSize,DWORDdwCreateFlags,LPSECURITY_ATTRIBUTESlpSecurityAttrs);1-8北京源智天下科技有限公司联系方式:例如,下面语句创建了一个工作者线程,其中指定线程的入口函数地址为function()函数的地址。UINTfunction(LPVOIDpParam){while(true){printf(Welcometo21VisualC++);Sleep(1000);printf(\t);return0;}}AfxBeginThread(function,NULL);//用于创建工作者线程1-9北京源智天下科技有限公司联系方式:创建用户界面线程•与工作者线程不同的是,用户界面线程通常用于处理用户的输入,响应用户产生的消息。为了建立一个用户界面线程,需要从CWinThread引出自定义的类,并将该类的运行时信息传给用户界面形式的AfxBeginThread()函数,以便创建用户界面线程。•一般说来,用户界面线程的创建过程一般需要先从基类CWinThread中派生出用户自定义的新类,再使用AfxBeginThread()函数创建线程。1-10北京源智天下科技有限公司联系方式:线程同步在有若干个线程并行运行的环境里,不同线程之间的同步是非常重要的。此处需要读者注意的是,此处的同步并不是指日常生活中说的两件事情同步,表示将两件事情同时来做,程序设计中的线程同步的目的是避免多个线程同时进行某些操作,使多个线程之间协调工作。比如在一座独木桥上,只能允许一个人通过,这时有两个方向相反的人要过桥。如果两个人同时要过桥,那么谁都不能过去,都会被阻塞在桥上。而线程同步就是要解决这个问题,一个时间段中只允许一个人对桥这个资源拥有控制权,如图17-7所示。桥甲乙资源1-11北京源智天下科技有限公司联系方式:线程同步概述在实际的多线程程序中,经常出现一些线程进行某些处理操作,而其他的线程必须对其处理结果进行了解或操作,正常情况下对这种处理结果的了解应当在其处理任务完成后进行,而很多时候该线程的任务并未完成。如果不采取适当的措施,其他线程往往会在线程处理任务结束前就去访问处理结果,这就很有可能得到错误的结果。在程序设计中,为了解决这个问题,或者说为了确保读线程读取到的是经过修改的变量,就必须在向变量写入数据时禁止其他线程对其的任何访问,直至赋值过程结束后再解除这种限制。这种为保证线程正确的处理结果而采取的保护措施即为线程同步。1-12北京源智天下科技有限公司联系方式:中的实现形式有很多种,为简单起见,此处只介绍最简单的一种同步对象:关键代码段。关键代码段也称为临界区,其是一种最简单的同步对象。关键代码段只可以被单个进程内的线程使用,其作用是保证只有一个线程可以申请到该对象。因此,可以让所有的线程都共享同一个关键代码段对象。读者可以看出,关键代码段类似于商场中的一个试衣间。同一时间只能有一个人进去。而另一个人若想进去,只有等到上一个人出来,将试衣间空出来才可以,如图17-8所示。关键代码段1-13北京源智天下科技有限公司联系方式:进程通信操作系统中实现同一台机器上的不同进程之间的通信是非常重要的。一般来说,进程间的通信方法有3种:剪贴板、邮槽和管道。1-14北京源智天下科技有限公司联系方式:剪贴板在读者的印象中,通常认为剪贴板是传输数据的媒介,用户要复制的数据首先保存到剪贴板中。这种想法不能说是正确的。因为实际上要复制的数据并不是真的保存在剪贴板上,而是在一块内存区域中。而剪贴板同这块内存区域相关联。或者说,由剪贴板来管理这块内存区域。例如,这里要将进程A中的内容通过剪贴板复制到进程B中,大致遵循以下步骤。(1)在进程A自己的4GB的地址空间中申请一块内存。(2)把要复制的数据写到申请的内存块当中;再把内存块交给剪贴板管理器中。(3)进程B由剪贴板中取出数据,如图17-14所示。1-15北京源智天下科技有限公司联系方式:北京源智天下科技有限公司联系方式:例如,下列语句从已连接的套接字上接收一个字符串,并将其放入字符串变量mm中。charaa[100];CStringmm;CSocket::Receive((void*)aa,100,0);mm=aa;1-17北京源智天下科技有限公司联系方式:剪贴板通信实例为了更好地理解以上讲述的函数,下面给出一个实例来详细地介绍如何使用剪贴板来实现进程间的通信。1-18北京源智天下科技有限公司联系方式:综合练习•实现一个多线程程序,其实现功能为:单击【启动】按钮后,系统当前时间将显示在文本框中,并实时更新。单击【停止】按钮后,时间停止,如图17-20所示。1-19北京源智天下科技有限公司联系方式:思考和习题•简述线程与进程的概念,并说明其区别。•在MFC应用程序中,是如何处理线程的?•程序设计中的线程同步的目的是避免多个线程同时进行某些操作,使多个线程之间协调工作。VisualC++提供了哪些方法来实现线程同步?•一个应用程序可以有一个或多个进程。一个进程可以有一个或多个线程,其中一个是主线程。VisualC++是如何创建进程并终止进程的?
本文标题:C++_编程_第十七章__线程同步与进程通信
链接地址:https://www.777doc.com/doc-7029002 .html