




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2022年年1月月16日日多核编程多核编程大连东软信息学院大连东软信息学院 多核课程组多核课程组 2022年年1月月16日日课程目录课程目录2022年年1月月16日日第第2单元主要内容单元主要内容u2.1 Windows API 多线程编程多线程编程u2.2 OpenMP 多线程编程多线程编程2022年年1月月16日日 第第4次课程主要内容次课程主要内容u2.1 Windows API 多线程编程多线程编程2022年年1月月16日日u 创建,终止线程的方法创建,终止线程的方法u 利用同步对象协调线程的运转和内存访问利用同步对象协调线程的运转和内存访问u资源互斥资源互斥u数据共享数据共享目的目的
2、2022年年1月月16日日引例引例u输出输出uHello Thread2022年年1月月16日日DWORD WINAPI helloFunc(LPVOID arg)DWORD WINAPI helloFunc(LPVOID arg) printf (“Hello Threadnprintf (“Hello Threadn); ); return 0; return 0; main()main() HANDLE hThread = HANDLE hThread = CreateThread(NULL, 0, helloFunc, NULL, 0, NULL); CreateThread(NULL
3、, 0, helloFunc, NULL, 0, NULL);WaitForSingleObject(hThread, INFINITE);WaitForSingleObject(hThread, INFINITE); 引例引例2022年年1月月16日日u定义定义: :u内核对象是由操作系统内核分配的,只能由内核访问的一个内核对象是由操作系统内核分配的,只能由内核访问的一个内存块,用来供系统和运用程序运用和管理各种系统资源。内存块,用来供系统和运用程序运用和管理各种系统资源。u线程对象、事件对象、文件对象、文件映射对象、作业对象、线程对象、事件对象、文件对象、文件映射对象、作业对象、互斥量、管
4、道对象、进程对象、信标对象和等待计时器对象互斥量、管道对象、进程对象、信标对象和等待计时器对象等。等。u对象都是经过调用函数来创建的对象都是经过调用函数来创建的 。u例如例如CreateThreadCreateThread内核对象内核对象2022年年1月月16日日HANDLE CreateThread (HANDLE CreateThread ( LPSECURITY_ATTRIBUTES lpThreadAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, /在系统中运用方法进程高级设置在系统中运用方法进程高级设置 DWORD dwSta
5、ckSize, / DWORD dwStackSize, /线程堆栈大小线程堆栈大小 LPTHREAD_START_ROUTINE lpStartAddress, LPTHREAD_START_ROUTINE lpStartAddress, /函数指针,指向实践运转的代码函数指针,指向实践运转的代码 LPVOID lpParameter, / LPVOID lpParameter, /参数指针参数指针 DWORD dwCreationFlags, / DWORD dwCreationFlags, /设置标志设置标志 LPDWORD lpThreadId); / LPDWORD lpThread
6、Id); /线程线程IDID创建线程创建线程2022年年1月月16日日LPTHREAD_START_ROUTINEDWORD WINAPI MyThreadStart(LPVOID p);创建线程创建线程2022年年1月月16日日BOOL CloseHandle (HANDLE hObject); 线程的终止线程的终止2022年年1月月16日日#include #include DWORD WINAPI helloFunc(LPVOID arg) printf (“Hello Threadn); return 0; main() HANDLE hThread = CreateThread(NU
7、LL, 0, helloFunc, NULL, 0, NULL); 主线程执行太快,子线程没有执行例子:线程的创建例子:线程的创建2022年年1月月16日日#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 (!threadD
8、one); / wasted cycles !线程的等待线程的等待2022年年1月月16日日v原型:原型:v v v等待一个线程等待一个线程DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds);线程的等待线程的等待2022年年1月月16日日引例引例u输出:输出:uHello ThreaduHello ThreaduHello ThreaduHello Thread2022年年1月月16日日v原型原型 v vThe WaitForMultipleObjects() function has the The WaitFor
9、MultipleObjects() function has the following parameters:following parameters:vnCountnCountvlpHandleslpHandlesvfWaitAllfWaitAllvdwMillisecondsdwMillisecondsDWORD WaitForMultipleObjects ( DWORD nCount, CONST HANDLE *lpHandles, / array BOOL fWaitAll, / wait for one or all DWORD dwMilliseconds);Wait for
10、 all: fWaitAll=TRUEWait for any: fWaitAll=FALSE多个线程的等待多个线程的等待2022年年1月月16日日const int numThreads = 4;const 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 hThreadnumT
11、hreads; HANDLE hThreadnumThreads; 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, TRUE, WaitForMultipleObjects(numT
12、hreads, hThread, TRUE, INFINITE)INFINITE) 引例处理方案引例处理方案2022年年1月月16日日问题思索问题思索u输出:输出:uHello Thread 0uHello Thread 1uHello Thread 2uHello Thread 32022年年1月月16日日DWORD WINAPI threadFunc(LPVOID pArg) int* p = (int*)pArg; int myNum = *p; printf( “Thread number %dn, myNum);. . ./ from main():for (int i = 0; i
13、 numThreads; i+) hThreadi = CreateThread(NULL, 0, threadFunc, &i, 0, NULL);问题处理?问题处理?2022年年1月月16日日下面的表将阐明出现问题的缘由 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 Tim
14、e 分析分析2022年年1月月16日日在多线程运用将遇到的问题多线程问题Deadlocks死锁Livelocks活锁Granularity粒度Load Imbalance负载平衡Data Races数据竞争多线程问题多线程问题数据竞争数据竞争2022年年1月月16日日v数据竞争vRead/Write 竞争vWrite/Write 竞争多线程问题多线程问题数据竞争数据竞争2022年年1月月16日日如何处理数据竞争如何处理数据竞争u在多线程运用中防止数据竞争的两种方法在多线程运用中防止数据竞争的两种方法u将变量的运用范围详细到每一个线程内部将变量的运用范围详细到每一个线程内部u变量声明在线程内变量
15、声明在线程内u线程本地存储线程本地存储Thread Local Storage (TLS)u以临界的方法控制并行访问以临界的方法控制并行访问同步对象同步对象uCritical section 临界区临界区uMutex 互斥互斥uSemaphore 信号量信号量uEvent 事件事件2022年年1月月16日日DWORD WINAPI threadFunc(LPVOID pArg) int myNum = *(int*)pArg); printf( “Thread number %dn, myNum);. . .for (int i = 0; i numThreads; i+) tNumi = i
16、; hThreadi = CreateThread(NULL, 0, threadFunc, &tNumi, 0, NULL);本地存储本地存储2022年年1月月16日日编程实现编程实现u1100 = ?2022年年1月月16日日oCritical section 临界区oMutex 互斥oSemaphore 信号量oEvent 事件同步对象同步对象2022年年1月月16日日临界区临界区u特点特点u轻量级轻量级u常用常用u非内核对象非内核对象2022年年1月月16日日临界区临界区u相关接口相关接口u CRITICAL_SECTION cs /定义临界区定义临界区u IntializeC
17、riticalSection(&cs) / 初始化临初始化临界区界区uDeleteCriticalSection(&cs) / 注销临界区注销临界区void WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); void WINAPI DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 2022年年1月月16日日 EnterCriticalSection(&cs) / 进入临界区LeaveCriticalSect
18、ion(&cs) / 退出临界区当临界区有其他线程时,线程将被阻塞不前往。当临界区没有线程时将前往void WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); void WINAPI LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 临界区临界区2022年年1月月16日日#define NUMTHREADS 4CRITICAL_SECTION g_cs; / 为什么定义成全局变量int g_sum = 0;DWORD WINAPI th
19、readFunc(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,threadFu
20、nc,NULL,0,NULL); WaitForMultipleObjects(NUMTHREADS, hThread, TRUE, INFINITE); DeleteCriticalSection(&g_cs);指点案例:临界区指点案例:临界区2022年年1月月16日日编程实现编程实现u11000000 = ?2022年年1月月16日日特点内核对象被一个线程拥有进程、线程间的同步 跨进程进展同步访问。为获得一个信号量要进展内核调用,开销大相关接口:CreateMutex() / 创建互斥量WaitForSingleObject() / 等待、加锁ReleaseMutex() / 解锁
21、互斥量互斥量2022年年1月月16日日实验工程实验工程u完成完成Windows*Threads多线程编多线程编程实验,工程二:临界区实验。程实验,工程二:临界区实验。2022年年1月月16日日v事件多用于以下情况:v通知计算完成v通知数据可用v通知音讯就绪v等待事件的接口: vWaitForSingleObject() /一个事件vWaitForMultipleObjects() /多个事件v事件的两种类型: vAuto-reset events /自动重置事件vManual-reset events /人工重置事件事件事件2022年年1月月16日日Auto-reset Events Manu
22、al-reset EventsEvent stays signaled until one waiting thread is releasedEvent stays signaled until explicitly reset to nonsignaled by an API callIf no thread is waiting, state remains signaledIf all waiting threads are released, state remains signaledAfter the thread is released, state is reset to n
23、onsignaledThreads not originally waiting may start wait and be released警告: 慎用 WaitForMultipleObjects() 等待一切的事件事件的两种类型事件的两种类型2022年年1月月16日日v bManualReset vTRUE: 人工重置事件vFALSE: 自动重置事件v bInitialState vTRUE: 激发态vFALSE: 未激发态HANDLE CreateEvent( LPSECURITY_ATTRIBUTES lpEventAttributes, BOOL bManualReset, / 确
24、定重置方式 BOOL bInitialState, / 确定事件的初始形状 LPCSTR lpName); / 事件称号事件的创建事件的创建2022年年1月月16日日SetEvent()ResetEvent()BOOL SetEvent( HANDLE event );BOOL ResetEvent( HANDLE event );事件的设置和重置事件的设置和重置2022年年1月月16日日HANDLE hObj 2; / 0 is event, 1 is thread DWORD WINAPI threadFunc(LPVOID arg) BOOL bFound = bigFind(); if
25、 (bFound) SetEvent(hObj0); / 满足激发条件 bigFound(); moreBigStuff(); return 0;指点案例:事件指点案例:事件2022年年1月月16日日 . . .hObj0 = CreateEvent(NULL, FALSE, FALSE, NULL); hObj1 = CreateThread(NULL,0,threadFunc,NULL,0,NULL);DWORD waitRet = WaitForMultipleObjects(2, hObj, FALSE, INFINITE); switch(waitRet) case WAIT_OBJ
26、ECT_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 ; 指点案例:事件指点案例:事件2022年年1月月16日日 . . . hObj0 = CreateEvent(NULL, FALSE, FALSE, NULL); hObj1 = CreateThread(NULL,0,threadFunc,NULL
27、,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(hObj1, INFINITE) ; case WAIT_OBJECT_0+1; printf (thread donen); break ; default: printf (“wait
28、error: ret %un, waitRet); break ; 指点案例:事件指点案例:事件2022年年1月月16日日特点:允许一个或者更多的线程进入临界区用于与多个可用资源的访问对信号量的操作可以概括为以下两种操作: Wait P(s): s = s-1Post V(s): s = s+1信号量信号量2022年年1月月16日日v原型: vv0 = count 0.HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpEventAttributes, LONG lSemInitial, /初始化的值 LONG lSemMax, /最大值 LPCST
29、R lpSemName); 信号量的创建信号量的创建2022年年1月月16日日vWaitForSingleObject() / wait操作v假设semaphore count = 0, v假设 semaphore count 0, 执行信号量减-1操作后前往.vpost操作BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG cReleaseCount, LPLONG lpPreviousCount);Wait和和Post操作操作2022年年1月月16日日v常用于:v控制对有限数据空间的访问v限制对一段给定代码的线程访问数量v控制对有限资源的访问v当信
30、号量定义为1时,类似于互斥量信号量的运用信号量的运用2022年年1月月16日日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); / Binary semaphore fd = fopen(“InFile, “r); / Open file for read for
31、(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);指点案例:信号量指点案例:信号量2022年年1月月16日日DWORD WINAPI CountFives(LPVOID arg) BOOL bDone = F
32、ALSE ; 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, INFINITE); / update global fiveL
33、etterCount += lCount; ReleaseSemaphore(hsem2, 1, NULL); 指点案例:信号量指点案例:信号量2022年年1月月16日日综合工程达成综合工程达成u问题描画问题描画u从一单精度浮点数串中找出乘积最大的延续的从一单精度浮点数串中找出乘积最大的延续的4个个浮点数。浮点数。u例如在以下浮点数串例如在以下浮点数串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言语编写并行程序完本言语编写并行程序完本钱工程。钱工程。2022年年1月月16日日HA
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
评论
0/150
提交评论