多线程编程(1).pdf





《多线程编程(1).pdf》由会员分享,可在线阅读,更多相关《多线程编程(1).pdf(13页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、win32 多线程编程要点2007/06/24 01:02 线程是进程的一条执行路径,它包含独立的堆栈和CPU 寄存器状态,每个线程共享所有的进程资源,包括打开的文件、信号标识及动态分配的内存等。一个进程内 的所有线程使用同一个地址空间,而这些线程的执行由系统调度程序控制,调度程序决定哪个线程可执行以及什么时候执行线程。线程有优先级别,优先权较低的线程必须等到优先权较高的线程执行完后再执行。在多处理器的机器上,调度程序可将多个线程放到不同的处理器上去运行,这样可使处理器任务平衡,并提高系统的运行效率。Windows是一种多任务的操作系统,在 Windows的一个进程内包含一个或多个线程。32
2、位 Windows环境下的 Win32 API 提供了多线程应用程序开发所需要的接口函数,而利用中提供的标准库也可以开发多线程应用程序,相应的类库封装了多线程编程的类,用户在开发时可根据应用程序的需要和特点选择相应的工具。为了使大家能全面地了解Windows多线程编程技术,本文将重点介绍 Win32 API 和 MFC 两种方式下如何编制多线程程序。多线程编程在 Win32方式下和 MFC 类库支持下的原理是一致的,进程的主线程在任何需 要的时候都可以创建新的线程。当线程执行完后,自动终止线程;当进程结束后,所有的线程都终止。所有活动的线程共享进程的资源,因此,在编程时需要考虑在多个线程访问同
3、一资源时产生冲突的问题。当一个线程正在访问某进程对象,而另一个线程要改变该对象,就可能会产生错误的结果,编程时要解决这个冲突。Win32 API 下的多线程编程Win32 API 是 Windows操作系统内核与应用程序之间的界面,它将内核提供的功能进行函数包装,应用程序通过调用相关函数而获得相应的系统功能。为了向应用 程序提供多线程功能,Win32 API 函数集中提供了一些处理多线程程序的函数集。直接用 Win32 API 进行程序设计具有很多优点:基于 Win32的应用程序执行代码小,运行效率高,但是它要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源。用 Win32 API
4、直接编写程序要求程序员对Windows系统内核有一定的了解,会占用程序员很多时间对系统资源进行管理,因而程序员的工作效率降低。1.用 Win32函数创建和终止线程Win32函数库中提供了操作多线程的函数,包括创建线程、终止线程、建立互斥区等。在应用程序的主线程或者其他活动线程中创建新的线程的函数如下:HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreat
5、ionFlags,LPDWORD lpThreadId);如果创建成功则返回线程的句柄,否则返回NULL。创建了新的线程后,该线程就开始启动执行了。但如果在 dwCreationFlags 中使用了 CREATE_SUSPENDED特性,那么线程并不马上执行,而是先挂起,等到调用ResumeThread后才开始启动线程,在这个过程中可以调用下面这个函数来设置线程的优先权:BOOL SetThreadPriority(HANDLE hThread,int nPriority);当调用线程的函数返回后,线程自动终止。如果需要在线程的执行过程中终止则可调用函数:VOID ExitThread(DWO
6、RD dwExitCode);如果在线程的外面终止线程,则可调用下面的函数:BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode);但应注意:该函数可能会引起系统不稳定,而且线程所占用的资源也不释放。因此,一般情况下,建议不要使用该函数。如果要终止的线程是进程内的最后一个线程,则线程被终止后相应的进程也应终止。2.线程的同步在 线程体内,如果该线程完全独立,与其他线程没有数据存取等资源操作上的冲突,则可按照通常单线程的方法进行编程。但是,在多线程处理时情况常常不是这样,线程之间经常要同时访问一些资源。由于对共享资源进行访问引起冲突是不可避免的
7、,为了解决这种线程同步问题,Win32 API 提供了多种同步控制对象来帮助程序员解决共享资源访问冲突。在介绍这些同步对象之前先介绍一下等待函数,因为所有控制对象的访问控制都要用到这个函数。Win32 API 提供了一组能使线程阻塞其自身执行的等待函数。这些函数在其参数中的一个或多个同步对象产生了信号,或者超过规定的等待时间才会返回。在等待函数未返回时,线程处于等待状态,此时线程只消耗很少的CPU 时间。使用等待函数既可以保证线程的同步,又可以提高程序的运行效率。最常用的等待函数是:DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMillise
8、conds);而函数 WaitForMultipleObject可以用来同时监测多个同步对象,该函数的声明为:DWORD WaitForMultipleObject(DWORD nCount,CONST HANDLE*lpHandles,BOOL bWaitAll,DWORD dwMilliseconds);文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3
9、Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3
10、M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD
11、6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9
12、L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10
13、R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:
14、CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 H
15、W9L3Y4R9Y1 ZC10R3M7G3B1(1)互斥体对象Mutex 对象的状态在它不被任何线程拥有时才有信号,而当它被拥有时则无信号。Mutex 对象很适合用来协调多个线程对共享资源的互斥访问。可按下列步骤使用该对象:首先,建立互斥体对象,得到句柄:HANDLE CreateMutex();然后,在线程可能产生冲突的区域前(即访问共享资源之前)调用WaitForSingleObject,将句柄传给函数,请求占用互斥对象:dwWaitResult=WaitForSingleObject(hMutex,5000L);共享资源访问结束,释放对互斥体对象的占用:ReleaseMutex(hMut
16、ex);互斥体对象在同一时刻只能被一个线程占用,当互斥体对象被一个线程占用时,若有另一线程想占用它,则必须等到前一线程释放后才能成功。(2)信号对象信 号对象允许同时对多个线程共享资源进行访问,在创建对象时指定最大可同时访问的线程数。当一个线程申请访问成功后,信号对象中的计数器减一,调用ReleaseSemaphore函数后,信号对象中的计数器加一。其中,计数器值大于或等于,但小于或等于创建时指定的最大值。如果一个应用在创建一个信号对象时,将其计数器的初始值设为,就阻塞了其他线程,保护了资源。等初始化完成后,调用 ReleaseSemaphore函数将其计数器增加至最大值,则可进行正常的存取访
17、问。可按下列步骤使用该对象:首先,创建信号对象:HANDLE CreateSemaphore();或者打开一个信号对象:HANDLE OpenSemaphore();然后,在线程访问共享资源之前调用WaitForSingleObject。共享资源访问完成后,应释放对信号对象的占用:ReleaseSemaphore();文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4
18、HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 Z
19、C10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档
20、编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B
21、4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1
22、 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1
23、文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1文档编码:CD6B9Q9L
24、9B4 HW9L3Y4R9Y1 ZC10R3M7G3B1(3)事件对象事件对象(Event)是最简单的同步对象,它包括有信号和无信号两种状态。在线程访问某一资源之前,需要等待某一事件的发生,这时用事件对象最合适。例如:只有在通信端口缓冲区收到数据后,监视线程才被激活。事 件对象是用 CreateEvent 函数建立的。该函数可以指定事件对象的类和事件的初始状态。如果是手工重置事件,那么它总是保持有信号状态,直到用ResetEvent 函数重置成无信号的事件。如果是自动重置事件,那么它的状态在单个等待线程释放后会自动变为无信号的。用 SetEvent 可以把事件对象设置成有信号状态。在建立事件时
25、,可以为对象命名,这样其他进程中的线程可以用OpenEvent函数打开指定名字的事件对象句柄。(4)排斥区对象在排斥区中异步执行时,它只能在同一进程的线程之间共享资源处理。虽然此时上面介绍的几种方法均可使用,但是,使用排斥区的方法则使同步管理的效率更高。使用时先定义一个CRITICAL_SECTION 结构的排斥区对象,在进程使用之前调用如下函数对对象进行初始化:VOID InitializeCriticalSection(LPCRITICAL_SECTION);当一个线程使用排斥区时,调用函数:EnterCriticalSection或者TryEnterCriticalSection;当要求
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 多线程 编程

限制150内