并行计算与多核程序设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
第四章Windows多线程编程及
调优->web课件
返回
在Windows平台下可以通过Windows的线程库来实现多线程编程,可以利用Win32 API或MF C以及.Net Framework提供的接口来实现。实现方式的多样化给Windows编程带来了很大的灵活性,但也使得多线程编程变得复杂。对于多线程的程序我们可以使用Visual Studio调试工具进行调试,也可以使用多核芯片厂家的线程分析与调试工具进行调试及优化。
Windows线程库介绍
Win32 API是Windows操作系统为内核以及应用程序之间提供的接口,将内核提供的功能进行函数封装,应用程序通过调用相关的函数获得相应的系统功能。Win32 API提供了一系列处理线程的函数接口,来向应用程序提供多线程的功能。
MFC是微软基础函数类库(Microsoft Foundation Classes),由微软提供的,用类库的方式将Wi n32 API 进行封装, 以类的方式提供给开发者。在MFC类库中,提供了对多线程的支持。由于MF C是在Win32 API 基础之上进行封装的,其基本原理与Win32 API的基本实现原理很类似。MFC 对同步对象作了封装,因此对用户编程实现来说更加方便。
.NET Framework由两部分构成:公共语言运行库(Common Language Runtime ,CLR)和Fra mework类库(Framework Class Library ,FCL)。CLR包括自己的文件加载器、垃圾收集器、安全系统等。CRL提供了一个可靠而完善的多语言运行环境。CLR是一个软件引擎,用于加载应用程序、检查错误、进行安全许可认证、执行和清空内存。Framework类库提供了所有应用程序模型都要使用的一个面向对象的API集合。.NET 基础类库的System.Threading命名空间提供了大量的类和接口来支持多线程。所有与多线程机制相关的类都存放在System.Threading命名空间中。其中Thread类用于创建及管理线程,ThreadPool类用于管理线程池等,此外还提供线程间通讯等实际问题的机制。
使用win32线程API
Win32 函数库中提供了操作多线程的函数,包括创建线程、管理线程、终止线程、线程同步等接口。
线程必须从一个指定的函数开始执行,该函数称为线程函数,具有如下原型:
DWORD WINAPI ThreadFunc (LPVOID lpvThreadParm);
线程创建
创建线程的函数如下:
HANDLE CreateThread (
LPSECURITY_ATTRIBUTES lpThreadAttributes,
SIZE_T dwStackSize,
LPTHREAD_START_ROUTINE lpStartAddress,
LPVOID lpParameter,
DWORD dwCreationFlags,
LPDWORD lpThreadId
);
CreateThread函数中需要传递6个参数。下面简单介绍一下这几个参数的用法:
第一个参数lpThreadAtt,是一个指向SECURITY- ATTRIBUTES结构的指针,该结构制定了线程的安全属性,缺省为NULL。
第二个参数dwStackSize,是栈的大小,一般设置为0。
第三个参数lpFun是新线程开始执行时,线程函数的入口地址。它必须是将要被新线程执行的函数地址,不能为NULL。
第四个参数lpParameter,是线程函数定义的参数。可以通过这个参数传送值,包括指针或者NULL 。
第五个参数dwCreationFlags,控制线程创建的附加标志,可以设置两种值。0表示线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数ResumeThread被调用;
第六个参数lpThreadID,为指向32位变量的指针,该参数接受所创建线程的ID号。
如果创建成功则返回线程的句柄,否则返回NULL。
线程管理
(1)设置线程的优先级
当一个线程被创建时,它的优先级等于它所属进程的优先级。可以通过调用SetThreadPriority函数来设置线程的相对优先级。线程的优先级是相对其所属的进程的优先级而言的。
例如:Bool SetThreadPriority (HANDLE hPriority , int nPriority) ;
参数hPriority 是指向待设置的线程句柄,线程与包含它的进程的优先级关系如下:
线程优先级= 进程优先级+ 线程相对优先级
(2)线程的挂起与恢复
进程中的每个线程都有挂起计数器(suspend count) 。当挂起计数器值为0 时,线程被执行;当挂起计数器值大于0 时,调度器不去调度该线程。
不能够直接访问线程的挂起计数器,可以通过调用Windows API 函数来改变它的值。可以通过调用SuspendThread()函数来挂起。可以通过调用ResumeThread()函数来恢复。这两个函数的原型如下:
DWORD SuspendThread(HANDLE hThread);
该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止。每次调用SuspendThr ead() 函数,线程将挂起计数器的值增1 。
DWORD ResumeThread(HANDLE hThread);
该函数用于结束线程的挂起状态来执行这个线程。每次调用ResumeThread() 函数,线程将挂起计数器的值减1 ,若挂起计数器的值为0,则不会再减。
(3)线程等待
Win32 API提供了一组能使线程阻塞其自身执行的等待函数WaitForSingleObject、WaitForMulti pleObject。这些函数在其参数中的一个或多个同步对象产生了信号,或者超过规定的等待时间才会返回。在等待函数未返回时,线程处于等待状态,线程只消耗很少的CPU时间。最常用的等待函数是:
DWORD WaitForSingleObject(HANDLE hHandle,
DWORD dwMilliseconds);
而函数WaitForMultipleObject可以用来同时监测多个对象,该函数的声明为:
DWORD WaitForMultipleObject(DWORD nCount,
CONST HANDLE *lpHandles,
BOOL bWaitAll,
DWORD dwMilliseconds);
线程终结