《多线程并行编程模型.ppt》由会员分享,可在线阅读,更多相关《多线程并行编程模型.ppt(53页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、20232023年年4 4月月2424日日多核多核编程程大大连东软信息学院信息学院多核多核课程程组 20232023年年4 4月月2424日日课程目程目录20232023年年4 4月月2424日日第第2单元主要内容元主要内容u2.1 Windows API 多多线程程编程程u2.2 OpenMP 多多线程程编程程20232023年年4 4月月2424日日 第第4次次课程主要内容程主要内容u2.1 Windows API 多多线程程编程程20232023年年4 4月月2424日日u 创建,建,终止止线程的方法程的方法u 利用同步利用同步对象象协调线程的运行和内存程的运行和内存访问n资源互斥源互斥
2、n数据共享数据共享目目标20232023年年4 4月月2424日日引例引例u输出出nHello Thread20232023年年4 4月月2424日日DWORD WINAPI helloFunc(LPVOID arg)DWORD WINAPI helloFunc(LPVOID arg)printf(“Hello Threadn”);printf(“Hello Threadn”);return 0;return 0;main()main()HANDLE hThread=HANDLE hThread=CreateThread(NULL,0,helloFunc,NULL,0,NULL);Create
3、Thread(NULL,0,helloFunc,NULL,0,NULL);WaitForSingleObject(hThread,INFINITE);WaitForSingleObject(hThread,INFINITE);引例引例20232023年年4 4月月2424日日u定定义:n内核内核对象是由操作系象是由操作系统内核分配的,只能由内核内核分配的,只能由内核访问的的一个内存一个内存块,用来供系,用来供系统和和应用程序使用和管理各种系用程序使用和管理各种系统资源。源。n线程程对象、事件象、事件对象、文件象、文件对象、文件映射象、文件映射对象、作象、作业对象、互斥量、管道象、互斥量、管道对
4、象、象、进程程对象、信象、信标对象和等待象和等待计时器器对象等。象等。n对象都是通象都是通过调用函数来用函数来创建的建的 。例如例如CreateThreadCreateThread()()内核内核对象象20232023年年4 4月月2424日日HANDLE HANDLE CreateThread CreateThread(LPSECURITY_ATTRIBUTES LPSECURITY_ATTRIBUTES lpThreadAttributes,lpThreadAttributes,/在系在系统中使用方法中使用方法进程高程高级设置置 DWORD dwStackSize,DWORD dwStac
5、kSize,/线程堆程堆栈大小大小 LPTHREAD_START_ROUTINE LPTHREAD_START_ROUTINE lpStartAddress,lpStartAddress,/函数指函数指针,指向,指向实际运行的代运行的代码 LPVOID lpParameter,LPVOID lpParameter,/参数指参数指针 DWORD dwCreationFlags,DWORD dwCreationFlags,/设置置标志志 LPDWORD lpThreadId);LPDWORD lpThreadId);/线程程IDID创建建线程程20232023年年4 4月月2424日日LPTHRE
6、AD_START_ROUTINEDWORD WINAPI MyThreadStart(LPVOID p);创建建线程程20232023年年4 4月月2424日日BOOL CloseHandle(HANDLE hObject);线程的程的终止止20232023年年4 4月月2424日日#include#include DWORD WINAPI helloFunc(LPVOID arg)printf(“Hello Threadn”);return 0;main()HANDLE hThread=CreateThread(NULL,0,helloFunc,NULL,0,NULL);What Happe
7、ns?What Happens?主线程执行太快,子线程没有执行例子:例子:线程的程的创建建20232023年年4 4月月2424日日#include#include BOOL threadDone=FALSE;DWORD WINAPI helloFunc(LPVOID 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 ide
8、a!Not a good idea!线程的等待程的等待20232023年年4 4月月2424日日v原型:原型:v等待一个等待一个线程程DWORD WaitForSingleObject(HANDLE hHandle,DWORD dwMilliseconds);线程的等待程的等待20232023年年4 4月月2424日日引例引例u输出:出:nHello ThreadnHello ThreadnHello ThreadnHello Thread20232023年年4 4月月2424日日v原型原型 v uThe The WaitForMultipleObjects()WaitForMultipleO
9、bjects()function has the function has the following parameters:following parameters:nCountnCountlpHandleslpHandlesfWaitAllfWaitAlldwMillisecondsdwMillisecondsDWORD WaitForMultipleObjects(DWORD nCount,CONST HANDLE*lpHandles,/array BOOL fWaitAll,/wait for one or all DWORD dwMilliseconds);Wait for all:
10、fWaitAll=TRUEWait for any:fWaitAll=FALSE多个多个线程的等待程的等待20232023年年4 4月月2424日日const int numThreads=4const int numThreads=4;DWORD WINAPI helloFunc(LPVOID arg)DWORD WINAPI helloFunc(LPVOID arg)printf(“Hello Threadn”);printf(“Hello Threadn”);return 0;return 0;main()main()HANDLE hThreadnumThreads;HANDLE hTh
11、readnumThreads;for(int i=0;i numThreads;i+)for(int i=0;i numThreads;i+)hThreadi=CreateThread(NULL,0,helloFunc,hThreadi=CreateThread(NULL,0,helloFunc,NULL,0,NULL);NULL,0,NULL);WaitForMultipleObjects(numThreads,hThread,WaitForMultipleObjects(numThreads,hThread,TRUE,INFINITE)TRUE,INFINITE)引例解决方案引例解决方案2
12、0232023年年4 4月月2424日日问题思考思考u输出:出:nHello Thread 0nHello Thread 1nHello Thread 2nHello Thread 320232023年年4 4月月2424日日DWORD WINAPI 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,N
13、ULL);输出的结果是什么?输出的结果是什么?问题解决?解决?20232023年年4 4月月2424日日下面的表将说明出现问题的原因 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 分析分析20232023年年4 4月月2424日日在多线程应用将遇到的问题多线程问题Deadlocks死锁Livelocks活锁Granularity粒度L
14、oad Imbalance负载平衡Data Races数据竞争多多线程程问题数据数据竞争争20232023年年4 4月月2424日日数据数据竞争争Read/Write 竞争争Write/Write 竞争争多多线程程问题数据数据竞争争20232023年年4 4月月2424日日如何解决数据如何解决数据竞争争u在多在多线程程应用中避免数据用中避免数据竞争的两种方法争的两种方法u将将变量的量的应用范用范围具体到每一个具体到每一个线程内部程内部o变量声明在量声明在线程内程内o线程本地存程本地存储Thread Local Storage(TLS)u以以临界的方法控制并行界的方法控制并行访问同步同步对象象o
15、Critical section 临界区界区oMutex 互斥互斥oSemaphore 信号量信号量oEvent 事件事件20232023年年4 4月月2424日日DWORD WINAPI threadFunc(LPVOID pArg)int myNum=*(int*)pArg);printf(“Thread number%dn”,myNum);.for(int i=0;i numThreads;i+)tNumi=i;hThreadi=CreateThread(NULL,0,threadFunc,&tNumi,0,NULL);本地存本地存储20232023年年4 4月月2424日日编程程实现u
16、1100=?20232023年年4 4月月2424日日oCritical section 临界区界区oMutex 互斥互斥oSemaphore 信号量信号量oEvent 事件事件同步同步对象象20232023年年4 4月月2424日日临界区界区u特点特点轻量量级常用常用非内核非内核对象象20232023年年4 4月月2424日日临界区界区u相关接口相关接口 CRITICAL_SECTION cs /定定义临界区界区 IntializeCriticalSection(&cs)/初始化初始化临界区界区DeleteCriticalSection(&cs)/注注销临界区界区void WINAPI In
17、itializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);void WINAPI DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);20232023年年4 4月月2424日日EnterCriticalSection(&cs)/进入临界区LeaveCriticalSection(&cs)/退出临界区当临界区有其他线程时,线程将被阻塞不返回。当临界区没有线程时将返回void WINAPI EnterCriticalSection(LPCRITICAL_SECTIO
18、N lpCriticalSection);void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection);临界区界区20232023年年4 4月月2424日日#define NUMTHREADS 4CRITICAL_SECTION g_cs;/为什么定义成全局变量int g_sum=0;DWORD WINAPI threadFunc(LPVOID arg)int mySum=bigComputation();EnterCriticalSection(&g_cs);g_sum+=mySum;/每次只有一个线程访问 Le
19、aveCriticalSection(&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);WaitForMultipleObjects(NUMTHREADS,hThread,TRUE,INFINITE);DeleteCriticalSection(&g_cs);指指导案例:案例:临界区界区20232023年年4 4月月2424日
20、日编程程实现u11000000=?20232023年年4 4月月2424日日特点内核对象被一个线程拥有进程、线程间的同步 跨进程进行同步访问。为获得一个信号量要进行内核调用,开销大相关接口:CreateMutex()/创建互斥量WaitForSingleObject()/等待、加锁ReleaseMutex()/解锁互斥量互斥量20232023年年4 4月月2424日日实验项目目u完成完成Windows*Threads多多线程程编程程实验,项目二:目二:临界区界区实验。20232023年年4 4月月2424日日v事件多用于下列情况:通知计算完成通知数据可用通知消息就绪v等待事件的接口:WaitF
21、orSingleObject()/一个事件WaitForMultipleObjects()/多个事件v事件的两种类型:Auto-reset events /自动重置事件Manual-reset events /人工重置事件事件事件20232023年年4 4月月2424日日Auto-reset Events Manual-reset EventsEvent stays signaled until one waiting thread is releasedEvent stays signaled until explicitly reset to nonsignaled by an API c
22、allIf no thread is waiting,state remains signaledIf all waiting threads are released,state remains signaledAfter the thread is released,state is reset to nonsignaledThreads not originally waiting may start wait and be released警告:慎用 WaitForMultipleObjects()等待所有的事件事件的两种事件的两种类型型20232023年年4 4月月2424日日v b
23、ManualReset TRUE:人工重置事件FALSE:自动重置事件v bInitialState TRUE:激发态FALSE:未激发态HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,BOOL bManualReset,/确定重置方式 BOOL bInitialState,/确定事件的初始状态 LPCSTR lpName);/事件名称事件的事件的创建建20232023年年4 4月月2424日日SetEvent()ResetEvent()BOOL SetEvent(HANDLE event);BOOL ResetEvent(
24、HANDLE event);事件的事件的设置和重置置和重置20232023年年4 4月月2424日日HANDLE hObj 2;/0 is event,1 is thread DWORD WINAPI threadFunc(LPVOID arg)BOOL bFound=bigFind();if(bFound)SetEvent(hObj0);/满足激发条件 bigFound();moreBigStuff();return 0;指指导案例:事件案例:事件20232023年年4 4月月2424日日 .hObj0=CreateEvent(NULL,FALSE,FALSE,NULL);hObj1=Cre
25、ateThread(NULL,0,threadFunc,NULL,0,NULL);DWORD waitRet=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;指指导案例:事件案例:事件
26、20232023年年4 4月月2424日日 .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(waitRet)case WAIT_OBJECT_0:printf(found it!n);WaitForSingleObject(hO
27、bj1,INFINITE);case WAIT_OBJECT_0+1;printf(thread donen);break;default:printf(“wait error:ret%un,waitRet);break;指指导案例:事件案例:事件20232023年年4 4月月2424日日 特点:允许一个或者更多的线程进入临界区用于与多个可用资源的访问对信号量的操作可以概括为以下两种操作:Wait P(s):s=s-1Post V(s):s=s+1信号量信号量20232023年年4 4月月2424日日 v原型:vv0=count 0.HANDLE CreateSemaphore(LPSECUR
28、ITY_ATTRIBUTES lpEventAttributes,LONG lSemInitial,/初始化的值 LONG lSemMax,/最大值 LPCSTR lpSemName);信号量的信号量的创建建20232023年年4 4月月2424日日 vWaitForSingleObject()/wait操作如果semaphore count=0,如果 semaphore count 0,执行信号量减-1操作后返回.vpost操作BOOL ReleaseSemaphore(HANDLE hSemaphore,LONG cReleaseCount,LPLONG lpPreviousCount);
29、Wait和和Post操作操作20232023年年4 4月月2424日日 v常用于:控制对有限数据空间的访问限制对一段给定代码的线程访问数量控制对有限资源的访问当信号量定义为1时,类似于互斥量信号量的使用信号量的使用20232023年年4 4月月2424日日 HANDLE hSem1,hSem2;FILE*fd;int fiveLetterCount=0;main()HANDLE hThreadNUMTHREADS;hSem1=CreateSemaphore(NULL,1,1,NULL);/Binary semaphore hSem2=CreateSemaphore(NULL,1,1,NULL)
30、;/Binary semaphore fd=fopen(“InFile”,“r”);/Open file for read for(int i=0;i NUMTHREADS;i+)hThreadi=CreateThread(NULL,0,CountFives,NULL,0,NULL);WaitForMultipleObjects(NUMTHREADS,hThread,TRUE,INFINITE);fclose(fd);printf(“Number of five letter words is%dn”,fiveLetterCount);指指导案例:信号量案例:信号量20232023年年4 4月
31、月2424日日 DWORD WINAPI CountFives(LPVOID arg)BOOL bDone=FALSE;char inLine132;int lCount=0;while(!bDone)WaitForSingleObject(hSem1,INFINITE);/access to input bDone=(GetNextLine(fd,inLine)=EOF);ReleaseSemaphore(hSem1,1,NULL);if(!bDone)if(lCount=GetFiveLetterWordCount(inLine)WaitForSingleObject(hSem2,INFI
32、NITE);/update global fiveLetterCount+=lCount;ReleaseSemaphore(hsem2,1,NULL);指指导案例:信号量案例:信号量20232023年年4 4月月2424日日综合合项目达成目达成u问题描述描述n从一从一单精度浮点数串中找出乘精度浮点数串中找出乘积最大的最大的连续的的4个浮点数。个浮点数。n例如在下列浮点数串例如在下列浮点数串1.0,2.0,3.0,4.0,5.0,6.0,5.0,3.0,3.0,2.0,9.0,1.0,2.0找到找到4.0,5.0,6.0,5.0.u采用采用Windows多多线程程API语言言编写并行程序完成本写
33、并行程序完成本项目。目。20232023年年4 4月月2424日日 HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpParameter,DWORD dwCreationFlags,LPDWORD lpThreadId);DWORD WINAPI MyThreadStart(LPVOID p);BOOL CloseHandle(HANDLE hObject);DWORD WaitForMulti
34、pleObjects(DWORD nCount,CONST HANDLE*lpHandles,BOOL fWaitAll,DWORD dwMilliseconds);总结20232023年年4 4月月2424日日 CRITICAL_SECTION cs IntializeCriticalSection(&cs)DeleteCriticalSection(&cs)EnterCriticalSection(&cs)LeaveCriticalSection(&cs)总结20232023年年4 4月月2424日日 HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpE
35、ventAttributes,BOOL bManualReset,BOOL bInitialState,LPCSTR lpName);BOOL SetEvent(HANDLE event);BOOL ResetEvent(HANDLE event);总结20232023年年4 4月月2424日日 HANDLE CreateSemaphore(LPSECURITY_ATTRIBUTES lpEventAttributes,LONG lSemInitial,/初始化的值 LONG lSemMax,/最大值 LPCSTR lpSemName);WaitForSingleObject()BOOL ReleaseSemaphore(HANDLE hSemaphore,LONG cReleaseCount,LPLONG lpPreviousCount);总结20232023年年4 4月月2424日日本章小本章小结u并行化程序开并行化程序开发流程流程n三个部分六个三个部分六个阶段段u分解模式分解模式n数据分解数据分解n任任务分解分解u数据数据竞争争n临界区界区n同步同步n互斥互斥20232023年年4 4月月2424日日谢谢!
限制150内