第5章Windows多线程编程
合集下载
相关主题
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
线程创建函数
创建线程还可以用process.h头文件中声明的C执行时期链接 库函数_beginthread。
hThread=_beginthread (void _cdec1(*start_address)(void*), unsigned stack_size, void *arglist); 第1个参数void _cdec1(*start_address)(void*) 是函数指针(函数入口地址) 第2个参数unsigned stack_size 规定了线程的堆栈大小,一般设置为0。 第3个参数void *arglist 是传递给线程函数的数据值。
使用win32线程API 使用win32线程API win32线程
Win32 函数库中提供了操作多线程的函数, 包括创建线程 、管理线程、终止线程、线程同步等接口。 线程函数
DWORD WINAPI ThreadFunc (LPVOID lpvThreadParm);
线程创建的函数
HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId
线程执行和资源存取
线程之间通信的两个基本问题是同步和互斥
线程同步是指线程之间所具有的一种制约关系,一个线程的执行 依赖另一个线程的消息,当它没有得到另一个线程的消息时应该 等待,直到消息到达时才被唤醒。 线程互斥是指对于共享资源,在各线程访问时的排它性。
Win32线程同步的实现
全局变量 事件(Event) 临界区(Critical section) 互斥量(Mutex) 信号量(Semaphore)
线程函数的语法如下: void _cdec1 ThreadProc(void*pParam) 例4.1 使用_beginthread创建线程的例子。
#include "stdafx.h" #include <windows.h> #include <process.h> #include <iostream> #include <fstream> using namespace std; void ThreadFunc1(PVOID param) { while(1) { Sleep(500); cout<<"This is ThreadFunc1"<<endl;} } void ThreadFunc2(PVOID param) { while(1) { Sleep(1000); cout<<"This is ThreadFunc2"<<endl;}} int main() { int i=0; _beginthread(ThreadFunc1,0,NULL); _beginthread(ThreadFunc2,0,NULL); Sleep(2000); cout<<"end"<<endl; return 0; }
Win32多线程的实现 Win32多线程的实现
下面这个程序首先创建两个线程,当输入为1时,执行线 程,否则挂起线程。例4.2
#include <windows.h> #include <iostream> using namespace std; DWORD WINAPI FunOne(LPVOID param){ while(true) { Sleep(1000); cout<<"hello! "; } return 0; } DWORD WINAPI FunTwo(LPVOID param){ while(true) { Sleep(1000); cout<<"world! "; } return 0; }
线程管理
设置线程的优先级
线程优先级 = 进程优先级 + 线程相对优先级
函数Bool SetThreadPriority (HANDLE hPriority , int nPriority)设置 线程的相对优先级。hPriority是指向待设置线程句柄,nPriority是线程的 相对优先级。
线程的挂起与恢复
进程中的每个线程都有挂起计数器(suspend count) 。当挂起计数 器值为0 时,线程被执行;当挂起计数器值大于0 时,调度器不去 调度该线程。
DWORD SuspendThread(HANDLE hThread);调用此函数挂起指定的 线程 DWORD ResumeThread(HANDLE hThread);调用此函数恢复指定的 线程
Win32多线程的实现 Win32多线程的实现(续) 多线程的实现(
int main(int argc, char* argv[]) { int input=0; HANDLE hand1=CreateThread (NULL, 0, FunOne, (void*)&input, CREATE_SUSPENDED, NULL); HANDLE hand2=CreateThread (NULL, 0, FunTwo, (void*)&input, CREATE_SUSPENDED, NULL); while(true){ cin>>input; if(input==1) { ResumeThread(hand1); ResumeThread(hand2); } else { SuspendThread(hand1); SuspendThread(hand2); } } TerminateThread(hand1,1); TerminateThread(hand2,1); return 0; }
线程管理
线程终结
在线程函数返回时,线程自动终止。 如果需要在线程的执行过程中终止,则可调用函数: VOID ExitThread(DWORD dwExitCode); 如果在线程的外面终止线程,则可调用下面的函数: BOOL TerminateThread(HANDLE hThread,DWORD dwExitCode); dwExitCode:用于指定线程的退出码。
);
线程创建函数
CreateThread函数中需传递6个参数,介绍这几个参数用法:
第1个参数lpThreadAttributes,是一个指向SECURITY_ATTRIBUTES结构的 指针,该结构制定了线程的安全属性,与主线程一样安全默认为NULL。 第2个参数dwStackSize,规定线程的堆栈大小(字节为单位),一般设置为0。 第3个参数lpStartAddress是新线程开始执行时,线程函数的入口地址。它必须 是将要被新线程执行的函数地址,不能为NULL。 第4个参数lpParameter,是线程函数定义的参数。可以通过这个参数传递值,包 括指针或者NULL。 第5个参数dwCreationFlags,控制线程创建的附加标志,可以设置两种值。如果 该参数为0,则表示线程在被创建后就会立即开始执行;如果该参数为 CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行 ,直至函数ResumeThread被调用。 第6个参数lpThreadID,为指向32位变量的指针,该参数接受所创建线程的ID号。 如果线程创建成功则返回线程的句柄,否则返回NULL.
Win32线程同步的实现 Win32线程பைடு நூலகம்步的实现
1.全局变量
进程中的所有线程均可以访问所有的全局变量,因而全局变量成 为Win32多线程通信的最简单方式。线程间可以利用此特性达到 线程同步的目的。 例4.3 使用全局变量同步线程的例子 使用全局变量时存在一些问题 主线程等待globalvar为真,如果不为真则一直循环,这样就 占用了CPU资源。 如果主线程的优先级高于ThreadFunc,则globalvar一直不会 被置为真。
多核程序设计
第五章 Windows多线程编程及调优 Windows多线程编程及调优
Windows线程库介绍 Windows线程库介绍
Win32 API是Windows操作系统为内核以及应用程序之 间提供的接口,将内核提供的功能进行函数封装,应用程 序通过调用相关的函数获得相应的系统功能。 MFC是微软基础函数类库(Microsoft Foundation Classes),由微软提供的,用类库的方式将Win32 API 进行封装, 以类的方式提供给开发者。 .NET Framework 由两部分构成:公共语言运行库( Common Language Runtime ,CLR)和Framework 类库(Framework Class Library ,FCL)。.NET 基 础类库的System.Threading命名空间提供了大量的类和 接口来支持多线程。所有与多线程机制相关的类都存放在 System.Threading命名空间中。
Win32线程同步的实现 Win32线程同步的实现
创建事件的函数原型为:HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState, LPCTSTR lpName) 第1个参数lpEventAttributes:是一个指向 SECURITY_ATTRIBUTES结构的指针。 第2个参数bManualReset:代表事件的类型,是手动清除事件信号 还是自动清除事件信号。True为手动清除。 第3个参数bInitialState :指明事件的初始状态,可指定为激发状态 或非激发状态。通常事件被初始化为非激发状态,表示用户还未准备 终止该线程。 第4个参数lpName:为指向事件对象的名字的指针,为事件对象指定 名字将会创建一个系统范围的事件对象,对所有进程可见并可用;若 指定NULL,系统会创建一个局部事件对象。若不需进行进程间通信 ,则推荐使用局部事件对象。
例4.1的解释说明 4.1的解释说明
新标准C++库头文件可省略扩展名.h,使用标准C++库时, 在紧接着所有的include指令之后,必须加入一条语句来指定 名空间:using namespace std; 可查看MSDN帮助系统。 函数Sleep()唯一的参数是一个32位整数,它表示线程在唤 醒(也就是激活)之前需要睡眠多少毫秒。由于基本上系统所 有运行情况都和线程有关,所以不能保证线程的实际睡眠时 间。Sleep的毫秒数仅仅是对操作系统的一个简单请求,线程 实际的睡眠时间可能会和请求时间有所不同。 将各线程的Sleep()睡眠时间作改变,再分析运行结果。
线程管理
线程等待
一组能使线程阻塞其自身执行的等待函数WaitForSingleObject、 WaitForMultipleObject。这些函数在其参数中的一个或多个同步对 象中产生了信号。或在超过规定的时间才会返回。在等待函数未返回 时,线程处于等待状态,线程只消耗很少的CPU时间。 DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds); DWORD WaitForMultipleObject(DWORD nCount,CONST HANDLE*lpHandles,BOOL bWaitALL,DWORD dwMilliseconds); 第1个参数nCount指定了需等待的句柄数(对象数); 第2个参数lpHandles指定了所等待的句柄对象数组; 第3个参数bWaitAll用于确定程序员是否希望该函数要等到所有的句柄 都被激发后才返回,还是当一个或几个句柄被激活后返回。 第4个参数dwMilliseconds指定等待的时间,一般设置为INFINITE WaitForMultipleObject可以用来同时监测多个对象。
Win32线程同步的实现 Win32线程同步的实现
2. 事件
事件(Event)是WIN32提供的最灵活的线程间同步 方式。 事件存在两种状态:
激发状态(signaled or true) 未激发状态(unsignal or false)
事件可分为两类:
手动设置:这种对象只能用程序来手动设置,在需要该 事件或者事件发生时,采用SetEvent及ResetEvent来 进行设置。 自动恢复:一旦事件发生并被处理后,将自动恢复到没 有事件状态,不需要再次设置。