《第5章 Win32 API 多线程编程.ppt》由会员分享,可在线阅读,更多相关《第5章 Win32 API 多线程编程.ppt(40页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、Neusoft Institute of Information14 一月 2023IT Education&Training大连东软信息学院大连东软信息学院 多核编程多核编程课程组课程组多核编程多核编程2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training第第5章章 Windows API 多线程编程多线程编程 2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training 目 标 创建,终止线程的方法 利用同步对象协调线
2、程的运行和内存访问资源互斥数据共享2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training1.Win32 句柄定义:内核对象是由操作系统内核分配的,只能由内核访问的一个内存块,用来供系统和应用程序使用和管理各种系统资源。线程对象、事件对象、文件对象、文件映射对象、作业对象、互斥量、管道对象、进程对象、信标对象和等待计时器对象等。对象都是通过调用函数来创建的。2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training2.Wi
3、n32 Thread CreationHANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,/在系统中使用方法进程高级设置 DWORD dwStackSize,/线程堆栈大小 LPTHREAD_START_ROUTINE lpStartAddress,/函数指针,指向实际运行的代码 LPVOID lpParameter,/参数指针 DWORD dwCreationFlags,/设置标志 LPDWORD lpThreadId);/线程ID2023/1/14Neusoft Institute of Information14 一月
4、 2023IT Education&TrainingLPTHREAD_START_ROUTINE DWORD WINAPI MyThreadStart(LPVOID p);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training3.线程的终止BOOL CloseHandle(HANDLE hObject);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子:线程的创建#include#include DWORD
5、 WINAPI helloFunc(LPVOID arg)printf(“Hello Threadn”);return 0;main()HANDLE hThread=CreateThread(NULL,0,helloFunc,NULL,0,NULL);What Happens?主线程执行太快,子线程没有执行2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training 4.线程的等待#include#include BOOL threadDone=FALSE;DWORD WINAPI helloFunc(LPVO
6、ID arg)printf(“Hello Threadn”);threadDone=TRUE;return 0;main()HANDLE hThread=CreateThread(NULL,0,helloFunc,NULL,0,NULL);while(!threadDone);/wasted cycles!Not a good idea!Not a good idea!2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training 4.线程的等待v原型:v等待一个线程DWORD WaitForSingleObje
7、ct(等待的对象等待的对象)HANDLE hHandle,(等待的时间(等待的时间 )DWORD dwMilliseconds);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training多个线程的等待v原型 v The WaitForMultipleObjects()function has the following parameters:nCountlpHandlesfWaitAlldwMillisecondsDWORD WaitForMultipleObjects(DWORD nCount,CONST
8、 HANDLE*lpHandles,/array BOOL fWaitAll,/wait for one or all DWORD dwMilliseconds);Wait for all:Wait for all:fWaitAllfWaitAll=TRUETRUEWait for aWait for anyny:fWaitAllfWaitAll=FALSEFALSE2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子const int numThreads=4;DWORD WINAPI hello
9、Func(LPVOID arg)printf(“Hello Threadn”);return 0;main()HANDLE hThreadnumThreads;for(int i=0;i numThreads;i+)hThreadi=CreateThread(NULL,0,helloFunc,NULL,0,NULL);WaitForMultipleObjects(numThreads,hThread,TRUE,INFINITE)2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training问题DWORD WINA
10、PI threadFunc(LPVOID pArg)int*p=(int*)pArg;int myNum=*p;printf(“Thread number%dn”,myNum);./from main():for(int i=0;i numThreads;i+)hThreadi=CreateThread(NULL,0,threadFunc,&i,0,NULL);输出的结果是什么?输出的结果是什么?输出的结果是什么?输出的结果是什么?2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training分析下面的表将说明出
11、现问题的原因 myNum=*pmyNum=2exitwaitT6p=pArgprint(2)waitT5launchmyNum=*pmyNum=2i+(i=2)T4-p=pArgcreate(&i)T3-launchi+(i=1)T2-create(&i)T1-i=0T0Thread 1Thread()Main Time 2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5 多线程问题数据竞争在多线程应用将遇到的问题在多线程应用将遇到的问题多线程问题Deadlocks死锁Livelocks活锁Gran
12、ularity粒度Load Imbalance负载平衡Data Races数据竞争2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training数据竞争Read/Write 竞争Write/Write 竞争5 多线程问题数据竞争2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training如何解决数据竞争v在多线程应用中避免数据竞争的两种方法:将变量的应用范围具体到每一个线程内部o变量声明在线程内o线程本地化Thread Local
13、 Storage(TLS)以临界的方法控制并行访问同步对象:oMutex 互斥oSemaphore 信号量oEvent 事件oCritical section 临界区2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5.1 本地存储DWORD WINAPI threadFunc(LPVOID pArg)int myNum=*(int*)pArg);printf(“Thread number%dn”,myNum);.for(int i=0;i numThreads;i+)tNumi=i;hThreadi
14、=CreateThread(NULL,0,threadFunc,&tNumi,0,NULL);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&TrainingoMutex 互斥oSemaphore 信号量oEvent 事件oCritical section 临界区5.2 同步对象2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5.2.1 互斥量特点内核对象被一个线程拥有进程、线程间的同步 跨进程进行同步访问。为获得一个信
15、号量要进行内核调用,开销大相关接口:CreateMutex()/创建互斥量WaitForSingleObject()/等待、加锁ReleaseMutex()/解锁2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5.2.2 临界区v特点:轻量级常用非内核对象v相关接口:v CRITICAL_SECTION cs /定义临界区 IntializeCriticalSection(&cs)/初始化临界区DeleteCriticalSection(&cs)/注销临界区void WINAPI Initializ
16、eCriticalSection(LPCRITICAL_SECTION lpCriticalSection);void WINAPI DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5.2.2 临界区 EnterCriticalSection(&cs)/进入临界区LeaveCriticalSection(&cs)/退出临界区当临界区有其他线程时,线程将被阻塞不返回。当临界区没有线程
17、时将返回void WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子:临界区#define NUMTHREADS 4CRITICAL_SECTION g_cs;/为什么定义成全局变量int g_sum=0;DWORD WINAP
18、I threadFunc(LPVOID arg)int mySum=bigComputation();EnterCriticalSection(&g_cs);g_sum+=mySum;/每次只有一个线程访问 LeaveCriticalSection(&g_cs);return 0;main()HANDLE hThreadNUMTHREADS;InitializeCriticalSection(&g_cs);for(int i=0;i NUMTHREADS;i+)hThreadi=CreateThread(NULL,0,threadFunc,NULL,0,NULL);WaitForMultipl
19、eObjects(NUMTHREADS,hThread,TRUE,INFINITE);DeleteCriticalSection(&g_cs);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5.2.3 事件v事件多用于下列情况:通知计算完成通知数据可用通知消息就绪v等待事件的接口:WaitForSingleObject()/一个事件WaitForMultipleObjects()/多个事件v事件的两种类型:Auto-reset events /自动重置事件Manual-reset events /
20、人工重置事件2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training事件的两种类型Auto-reset Events Manual-reset EventsEvent stays signaled until one waiting thread is released.Event stays signaled until explicitly reset to nonsignaled by an API call.If no thread is waiting,state remains signaled
21、.If all waiting threads are released,state remains signaled.After the thread is released,state is reset to nonsignaled.Threads not originally waiting may start wait and be released.警告:慎用 WaitForMultipleObjects()等待所有的事件2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training事件的创建v bMa
22、nualReset:TRUE:人工重置事件人工重置事件FALSE:自动重置事件自动重置事件v bInitialState:TRUE:激发态激发态FALSE:未激发态未激发态HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,/确定重置方式 BOOL bInitialState,/确定事件的初始状态 LPCSTR lpName);/事件名称2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training事件的设置和重
23、置SetEvent()ResetEvent()BOOL SetEvent(HANDLE event);BOOL ResetEvent(HANDLE event);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子:事件HANDLE hObj 2;/0 is event,1 is thread DWORD WINAPI threadFunc(LPVOID arg)BOOL bFound=bigFind();if(bFound)SetEvent(hObj0);/满足激发条件 bigFound();mo
24、reBigStuff();return 0;2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子:事件 .hObj0=CreateEvent(NULL,FALSE,FALSE,NULL);hObj0=CreateEvent(NULL,FALSE,FALSE,NULL);hObj1=hObj1=CreateThread(NULL,0,threadFunc,NULL,0,NULL);CreateThread(NULL,0,threadFunc,NULL,0,NULL);DWORD waitRet=DWO
25、RD waitRet=WaitForMultipleObjects(2,hObj,FALSE,INFINITE);WaitForMultipleObjects(2,hObj,FALSE,INFINITE);switch(waitRet)case WAIT_OBJECT_0:printf(found it!n);WaitForSingleObject(hObj1,INFINITE);case WAIT_OBJECT_0+1 printf(thread donen);break;default:printf(“wait error:ret%un,waitRet);break;2023/1/14Ne
26、usoft Institute of Information14 一月 2023IT Education&Training例子:事件 .hObj0=CreateEvent(NULL,FALSE,FALSE,NULL);hObj1=CreateThread(NULL,0,threadFunc,NULL,0,NULL);/*Do some other work while thread executes search*/DWORD waitRet=WaitForMultipleObjects(2,hObj,FALSE,INFINITE);switch(waitRetswitch(waitRet)c
27、ase WAIT_OBJECT_0:case WAIT_OBJECT_0:printfprintf(found it!n);(found it!n);WaitForSingleObject(hObj1,INFINITE);WaitForSingleObject(hObj1,INFINITE);case WAIT_OBJECT_0+1;case WAIT_OBJECT_0+1;printfprintf(thread donen);(thread donen);break;break;default:default:printf(printf(“wait error:ret%un,waitRet)
28、;wait error:ret%un,waitRet);break;break;2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training5.2.4 信号量 特点:允许一个或者更多的线程进入临界区用于与多个可用资源的访问对信号量的操作可以概括为以下两种操作:Wait P(s):s=s 1Post V(s):s=s+12023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training信号量的创建 v原型:vv0=count 0.HAN
29、DLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpEventAttributes,LONG lSemInitial,/初始化的值 LONG lSemMax,/最大值 LPCSTR lpSemName);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&TrainingWAIT 和POST 操作 vWaitForSingleObject()/wait操作如果semaphore count=0,如果 semaphore count 0,执行信号量减-1操作后返回.vpost操作BOO
30、L ReleaseSemaphore(HANDLE hSemaphore,LONG cReleaseCount,LPLONG lpPreviousCount);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training信号量的应用 v常用于:控制对有限数据空间的访问限制对一段给定代码的线程访问数量控制对有限资源的访问当信号量定义为1时,类似于互斥量2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子:信号量 HAN
31、DLE hSem1,hSem2;FILE*fd;int fiveLetterCount=0;main()HANDLE hThreadNUMTHREADS;hSem1=CreateSemaphore(NULL,1,1,NULL);/Binary semaphore hSem2=CreateSemaphore(NULL,1,1,NULL);/Binary semaphore fd=fopen(“InFile”,“r”);/Open file for read for(int i=0;i NUMTHREADS;i+)hThreadi=CreateThread(NULL,0,CountFives,NU
32、LL,0,NULL);WaitForMultipleObjects(NUMTHREADS,hThread,TRUE,INFINITE);fclose(fd);printf(“Number of five letter words is%dn”,fiveLetterCount);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training例子:信号量 DWORD WINAPI CountFives(LPVOID arg)BOOL bDone=FALSE;char inLine132;int lCount=0;wh
33、ile(!bDone)WaitForSingleObject(hSem1,INFINITE);/access to input bDone=(GetNextLine(fd,inLine)=EOF);ReleaseSemaphore(hSem1,1,NULL);if(!bDone)if(lCount=GetFiveLetterWordCount(inLine)WaitForSingleObject(hSem2,INFINITE);/update global fiveLetterCount+=lCount;ReleaseSemaphore(hsem2,1,NULL);2023/1/14Neuso
34、ft Institute of Information14 一月 2023IT Education&Training6.总结 HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);DWORD WINAPI MyThreadStart(LPVOID p);BOOL CloseHandle(HANDL
35、E hObject);DWORD WaitForMultipleObjects(DWORD nCount,CONST HANDLE*lpHandles,BOOL fWaitAll,DWORD dwMilliseconds);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training6.总结 CRITICAL_SECTION cs IntializeCriticalSection(&cs)DeleteCriticalSection(&cs)EnterCriticalSection(&cs)LeaveCritic
36、alSection(&cs)2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training6.总结 HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,BOOL bInitialState,LPCSTR lpName);BOOL SetEvent(HANDLE event);BOOL ResetEvent(HANDLE event);2023/1/14Neusoft Institute of Information14 一月 2023IT Education&Training6.总结 HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpEventAttributes,LONG lSemInitial,/初始化的值 LONG lSemMax,/最大值 LPCSTR lpSemName);WaitForSingleObject()BOOL ReleaseSemaphore(HANDLE hSemaphore,LONG cReleaseCount,LPLONG lpPreviousCount);2023/1/14