欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    【教学课件】第11章多线程编程.ppt

    • 资源ID:69843373       资源大小:483.50KB        全文页数:22页
    • 资源格式: PPT        下载积分:11.9金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要11.9金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    【教学课件】第11章多线程编程.ppt

    第11章 多线程编程在Windows平台上可以同时执行多个任务。例如,可以在使用Word的同时使用VC;使用Word的时候又可以一边打印文档,一边继续编辑文档。Word和VC的并行运行叫进程,在Word中一边打印一边编辑叫做线程。也就是说,操作系统内可以同时运行多个进程,而进程内又可以有多个线程。可以看到,多线程可以提高程序的并发性,同时也可以提高程序的工作效率。例如,M个人搬N个箱子,那么当然是M的值越大搬的速度越快。线程也是如此,例如经常听说某某软件采用多线程下载,速度非常快,这就是多线程的功劳。但是这里要注意,在单CPU平台下,多线程程序在某一时刻只有一个线程在运行,多线程程序运行是交替进行的。如果是多个CPU,当然就有可能多个线程同时运行。虽然单CPU平台每一时刻只能有一个线程在工作,但是这种机制可以让作业快的线程有机会先执行完毕,并且在有时多线程的很多操作与操作系统有关,使用多线程确实能在很大程度上提高程序工作的效率,提高程序的并发性。至于线程间如何切换交替运行,到后面第11.3节线程同步中会结合例子说明。11.1 如何创建线程创建一个线程主要分为两步,即首先调用API函数CreateThread创建一个线程,然后编写线程函数。创建线程完毕以后,主线程会与创建后的线程同时运行。11.1.1 使用CreateThread创建一个线程实际上,main函数或者WinMain函数在运行以后就是一个线程通常叫主线程,所以可以将线程简单地理解为一个函数。API函数CreateThread可以创建一个线程来指向当前进程的虚拟地址空间,也就是说执行一个函数。下面是这个函数的原型。HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,SIZE_T dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);11.1.2 编写线程函数CreateThread函数的第3个参数需要设置一个线程函数地址。CreateThread创建线程成功以后,新的线程就从这个函数执行。线程函数必须定义成下面的形式。DWORD WINAPI ThreadProc(LPVOID lpParameter);CreateThread的第4个参数lpParameter将通过lpParameter被传递进来。11.1.3 示例创建一个线程下面代码显示如何用API函数创建一个线程。在这个线程中输出“Hello MyThread”。程序在开始时候创建了一个线程,并且传递了2个主要的参数进去,其他的参数都使用建议值。第3个参数表示线程函数,第4个参数表示给线程函数的参数。线程函数名叫MyThreadProc,参数值是“Hello MyThreadn”,这样MyThreadProc就会在lpParameter中得到这个“Hello MyThreadn”。由于参数类型是LPVOID(void*),所以需要将LPVOID再转换成char*或者const char*类型,到此接收参数工作完毕,开始用printf输出。11.1.4 示例创建多个线程,模拟机票订购在上一小节中讲述了如何创建线程,下面用一个经典的例子来阐述如何创建多个线程。一架飞机有200个座位,现有两个订购地点提供订票服务。飞机票的编号从1200,现在用多线程实现订购过程。代码如下。可以看到,利用第1节学过的知识,上述程序中创建了2个线程,分别模拟2个飞机售票处,飞机票由两个售票处交替地售出。但是这种售票方式存在一个问题,下节将会介绍。11.2 线程同步在多线程程序执行过程中,会有多个线程访问同一块数据临界资源,那么就需要对临界资源进行读写保护。完成这一工作的过程就是线程同步。上面一节的最后一个例子中,创建2个线程模拟2个飞机售票处售票的过程,200张飞机票由2个线程交替出售,这其中存在一个问题,假如修改一下Shop1的while循环代码,如下所示。while(1)if(tickets 0)Sleep(1);/这里添加一行,用来延时printf(Shop1 Sell a Ticket:%dn,tickets);tickets-;elsereturn 0;11.2.1 线程之间切换时间片本章的开始曾经介绍过,单CPU平台下某一时刻只能有一个线程在运行。但是多线程程序的运行与并行运行相似。这是因为操作系统将CPU的运行时间分成多个小块,每个小块被称为一个时间片。每个线程都运行一个时间片,当时间片限定的时间到,还在运行的线程就将CPU交给其他线程使用,如图所示,假设时间片大小为0.01ms,则线程1运行了0.01ms后暂停,将CPU交给线程2使用。当线程2运行0.01ms后,再将CPU交给线程3使用,依此类推,直到所有线程都运行结束。由于时间片是如此的小,以至于人们无法感觉到,所以多个线程看似在“并行”地运行。11.2.2 使用互斥对象来同步线程前面说过,在多线程程序设计过程中,对于临界资源的读写需要进行保护。也就是说,一个线程正在对这个临界资源进行读写时,其他线程就不能对其进行读写,这个过程叫做线程的同步。线程同步是通过一些操作系统的内核对象来实现的。通常,内核对象有事件对象、互斥对象等,其功能就是为了对临界资源进行保护。这里先介绍一下如何使用互斥对象。API函数CreateMutex可以用来创建一个互斥对象,其原型如下。HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,BOOL bInitialOwner,LPCTSTR lpName);11.2.3 示例修改多线程例子,使用互斥对象对其进行同步下面在飞机售票系统的原代码中添加一些代码,使一个线程在操作临界资源时,其他线程不能操作。具体代码如下。/eg_2_multithread_selltickets2.cpp飞机售票系统-修改以后#include stdafx.h#include#include DWORD WINAPI Shop1(LPVOID lpParameter);11.2.4 示例使用命名互斥对象判断程序是否多次运行前面一节讲述了如何使用互斥对象来进行线程同步,使用API函数CreateMutex可以创建一个互斥对象,但是第3个参数使用的是NULL,表示不起名字。本节通过一个例子,告诉读者互斥对象的另外一个用途命名互斥对象判断程序是否运行多次。编写一个程序,正常运行输出“Hello world”,如果重复运行输出“Sorry”。11.3 线程同步的其他方法除了互斥对象,还有其他方法可以实现线程的同步。不同的方法适用于不同的场合,但是读者只要掌握其中一种就可满足大部分多线程应用,下面对其他方法做一简单介绍。11.3.1 示例使用事件对象完成线程的同步下面给出使用事件对象完成线程同步的飞机售票系统。粗体字表示与互斥对象示例不同的地方。11.3.2 示例使用临界区完成线程的同步事件对象和互斥对象的使用非常相像。下面的例子使用临界区完成线程同步,其代码也与上面2个示例的代码非常相像,粗体字表示与上面2个示例代码不同的地方。11.4 线程同步导致的死锁及预防由于线程在同步的时候会调用一些方法来等待,当发生一些事件以后再继续运行,但是如果一个线程发生了永远等待的现象,那么这个现象就称为死锁。例如在线程函数中,一些分支语句中经常会有return关键字,如果这个分支语句在EnterCriticalSection和LeaveCriticalSection之间,那么这个代码就是危险的。其中存在的问题以示例演示。11.4.1 示例使用临界区时,意外退出导致死锁上一节的最后一个示例存在一个问题,就是有一个线程永远不会退出。下面添加一些输出项来。测试其是否没有退出。输出结果表明,Shop1没有调用return返回,也就是说,Shop1一直等待,这种一直等待的现象就是死锁。造成这种现象的原因很明显,Shop2调用EnterCriticalSection进入临界区,然后操作临界资源,但是由于tickets等于0,导致其调用return直接返回,没有运行到LeaveCriticalSection离开临界区。当然,这就使正在使用EnterCriticalSection等待进入临界区的Shop1就永远也进不去。11.4.2 预防死锁死锁在实际开发中也是非常容易出现的,其原因可能是程序员不良的编程规范、代码的重复开发以及一些其他因素造成的。所以为了预防死锁,程序员应该养成良好的编程规范,并且在设计上让程序合理。例如,上面的情况使用互斥对象就不会出现死锁,因为互斥对象的拥有者线程会在结束时,放弃对其使用权,其他线程可以接着拥有这个互斥对象。而临界区不可以。11.5 应用案例使用多线程完善文件分割工具在前面章节的应用案例中,已经制作了一个文件分割工具。但是程序存在一个问题,就是当单击“开始分割”或“开始合并”的时候,程序会无法响应,直到操作完成才能继续操作。本节将通过线程来解决以上问题。11.5.1 案例效果图程序界面与第5章的程序界面基本一致。当选择“分割文件”选项卡时,程序界面如图所示。当选择“合并文件”选项卡时,程序界面如图所示。11.5.2 需要掌握的知识点本案例中需要掌握的知识点如下。对话框编程基础;文件操作基础;多线程编程;基本控件的使用。11.5.3 开发过程由于本案例属于先前案例的升级版,所以可以在先前案例中稍作修改,同时也避免了界面设计的麻烦。具体操作步骤如下。(1)创建第5章应用案例工程复本,将项目目录重命名为eg_6_filesplitter_plus。(2)打开工程,首先修改CFileSplitter类的声明,下列代码中粗体字表示修改部分。(3)在构造函数中初始化新添加的成员pTargetWnd。(4)修改Split与Join,只在其中创建线程,分割与合并的工作交给线程处理。(5)编写线程函数,完成分割与合并的功能。(6)至此,文件分割类CFileSplitter已经修改完毕。(7)当分割文件结束,CFileSplitter对象会向分割窗口发送UM_SPLITOK消息,手动添加UM_SPLITOK消息处理。(8)当合并文件结束,CFileSplitter对象会向分割窗口发送UM_JOINOK消息,手动添加UM_JOINOK消息处理。11.6 小结本章主要学习了多线程编程的相关知识,了解了多线程的优点及多线程同步、死锁等相关概念,最后通过一个应用案例,使用多线程解决前面案例中的不足。使用多线程提高了程序的并发,同时也带来管理上的复杂度,所以多线程编程不是任何时候都适用的。当多个线程对同一数据进行读写时,必须为此数据采取同步措施。如果将线程函数定义为类成员,必须将函数定义为static函数。

    注意事项

    本文(【教学课件】第11章多线程编程.ppt)为本站会员(wuy****n92)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开