Windows线程同步和互斥.ppt_第1页
Windows线程同步和互斥.ppt_第2页
Windows线程同步和互斥.ppt_第3页
Windows线程同步和互斥.ppt_第4页
Windows线程同步和互斥.ppt_第5页
已阅读5页,还剩29页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Windows线程同步和互斥,Windows线程同步机制,事件(Event) 临界区(Critical Section) 互斥量(Mutex) 信号量(Semaphore),同步机制说明,互斥量与临界区的作用非常相似,但互斥量是可以命名的,也就是说它可以跨越进程使用。 如果只为了在进程内部用的话使用临界区会带来速度上的优势并能够减少资源占用量。 互斥量是跨进程的,一旦被创建,就可以通过名字打开它。创建互斥量需要的资源更多。,同步机制说明(续),互斥量,信号量和事件都可以跨进程来实现同步数据操作。 互斥量:资源独占使用 信号量:资源计数器,事件,事件对象可以通过通知操作的方式来保持线程的同步。并

2、且可以实现不同进程中的线程同步操作。 事件是WIN32中最灵活的线程间同步机制。 事件存在两种状态: 激发状态(Signaled or True) 未激发状态(Unsignaled or False),事件,事件可分为两类: 手动设置: 这种对象只可能用程序手动设置,在需要该事件或者事件发生时,采用SetEvent及ResetEvent来进行设置。 自动恢复: 一旦事件发生并被处理后,自动恢复到没有事件状态,不需要再次设置。,事件函数原型,函数原型: HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,/ SECURITY_AT

3、TRIBUTES结构指针,可为NULLBOOL bManualReset, / 手动/自动/ TRUE:在WaitForSingleObject后必须手动调用ResetEvent清除信号/ FALSE:在WaitForSingleObject后,系统自动清除事件信号BOOL bInitialState, /初始状态LPCTSTR lpName /事件的名称);,事件函数原型(续),使用“事件”机制应注意以下事项: 如果跨进程访问事件,必须对事件命名,在对事件命名的时候,要注意不要与系统命名空间中的其它全局命名对象冲突; 事件是否要自动恢复; 事件的初始状态设置。 由于event对象属于内核对象

4、,故进程B可以调用OpenEvent函数通过对象的名字获得进程A中event对象的句柄,然后将这个句柄用于ResetEvent、SetEvent和WaitForMultipleObjects等函数中。此法可以实现一个进程的线程控制另一进程中线程的运行,例如: HANDLE hEvent=OpenEvent(EVENT_ALL_ACCESS,true,MyEvent); ResetEvent(hEvent);,事件例子,三个线程: 主线程 读线程 写线程 读线程必须在写线程操作结束后才能进行读; 主线程必须等读和写线程结束后才能结束,代码,include stdafx.h #include #i

5、nclude #include #include HANDLE evRead,evFinish; void ReadThread(LPVOID param) WaitForSingleObject(evRead, INFINITE); coutReadingendl; SetEvent(evFinish); void WriteThread(LPVOID param) coutWritingendl; SetEvent(evRead); ,代码(续),int main(int argc, char* argv) evRead= CreateEvent(NULL,FALSE,FALSE,NULL

6、); evFinish= CreateEvent(NULL,FALSE,FALSE,NULL); _beginthread(ReadThread,0,NULL); _beginthread(WriteThread,0,NULL); WaitForSingleObject(evFinish, INFINITE); coutEnd.endl; return 0; ,临界区,临界区是保证在某一时刻只有一个线程能访问数据的简便办法。在任意时刻只允许一个线程对共享资源进行访问。 如果有多个线程试图同时访问临界区,那么在有一个线程进入后其他所有试图访问此临界区的线程将被挂起,并一直持续到进入临界区的线程离

7、开。临界区在被释放后,其他线程可以继续抢占,并以此达到用原子方式操作共享资源的目的。,临界区(续),临界区包含两个操作原语: EnterCriticalSection() 进入临界区 LeaveCriticalSection() 离开临界区 EnterCriticalSection()语句执行后代码将进入临界区以后无论发生什么,必须确保与之匹配的LeaveCriticalSection()都能够被执行到。否则,临界区保护的共享资源将永远不会被释放。 虽然临界区同步速度很快,但却只能用来同步本进程内的线程,而不可用来同步多个进程中的线程。,临界区Win32 API,创建临界区为了创建临界区,首先

8、必须在进程中分配一个全局CRITICAL_SECTION数据结构: CRITICAL_SECTION gCriticalSection; 使用临界区使用临界区之前,必须调用InitializeCriticalSection函数初始化: VOID InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 进入临界区调用EnterCriticalSection函数进入临界区:VOID EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 离开临界区调用Leave

9、CriticalSection函数退出了临界区:VOID LeaveCriticalSection(LPCRITICAL_SECTION lpCriticalSection); 删除临界区 调用DeleteCriticalSection函数删除临界区:VOID DeleteCriticalSection(LPCRITICAL_SECTION lpCriticalSection);,临界区一般用法, EnterCriticalSection( ,临界区注意事项,关于临界区的使用,有下列注意点: 每个共享资源使用一个CRITICAL_SECTION变量; 不要长时间运行关键代码段,当一个关键代码段

10、长时间运行时,其他线程就会进入等待状态,这会降低应用程序的运行性能; 如果需要同时访问多个资源,则可能连续调用EnterCriticalSection; Critical Section不是OS核心对象,如果进入临界区的线程挂了,将无法释放临界资源。这个缺点在Mutex中得到了弥补。,临界区例子,一个银行系统中两个线程执行取款操作,一个使用ATM机,另一个使用存折在柜台取款。如果不加于控制,会使得账户余额为负数。,代码,#include stdafx.h #include #include #include #include int total =1000; HANDLE evFin2; CR

11、ITICAL_SECTION cs; void WithDrawThread1(LPVOID param) EnterCriticalSection( ,代码(续),void WithDrawThread2(LPVOID param) EnterCriticalSection( ,代码(续),int main(int argc, char* argv) evFin0 = CreateEvent(NULL,FALSE,FALSE,NULL); evFin1 = CreateEvent(NULL,FALSE,FALSE,NULL); InitializeCriticalSection( ,互斥量,

12、互斥量跟临界区很相似,只有拥有互斥对象的线程才具有访问资源的权限。 由于互斥对象只有一个,因此就决定了任何情况下此共享资源都不会同时被多个线程所访问。 当前占据资源的线程在任务处理完后应将拥有的互斥对象交出,以便其他线程在获得后得以访问资源。 互斥量比临界区复杂。因为使用互斥不仅仅能够在同一应用程序不同线程中实现资源的安全共享,而且可以在不同应用程序的线程之间实现对资源的安全共享。,互斥量,用CreateMutex函数创建互斥量: HANDLE CreateMutex(LPSECURITY_ATTRIBUTES lpMutexAttributes,/ 安全属性结构指针,可为NULLBOOL b

13、InitialOwner, /是否占有该互斥量,TRUE:占有,FALSE:不占有LPCTSTR lpName /信号量的名称);,其它API,打开一个互斥量 :OpenMutex函数:HANDLE OpenMutex(DWORD fdwAccess, / 值为SYNCHRONIZE或MUTEX_ALL_ACCESSBOOL fInherit,LPTSTR lpszName); 释放一个互斥量 : ReleaseMutex函数:BOOL ReleaseMutex(HANDLE hMutex);该函数将互斥量从无信号状态变到有信号状态。,互斥和临界区的比较,互斥量例子代码,#include st

14、dafx.h #include #include #define THREAD_INSTANCE_NUMBER 3 LONG g_RessourceInUse=FALSE; LONG g_iCounter=0; void ThreadProc(void *pData) int ThreadNumTemp=(*(int *) pData); HANDLE hMutex; coutThreadProc:ThreadNumTemp in Running!endl; if (hMutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,Mutex.Test)=NULL) coutOp

15、en mutex error!endl; WaitForSingleObject(hMutex,INFINITE); coutThreadProc:ThreadNumTemp gets the mutex.endl; ReleaseMutex(hMutex); CloseHandle(hMutex); coutThreadProc:ThreadNumTemp end.endl; ,互斥量例子代码(续),int main(int argc, char* argv) DWORD IDTHREAD_INSTANCE_NUMBER; HANDLE hTHREAD_INSTANCE_NUMBER; HA

16、NDLE hMutex; int i; if (hMutex=OpenMutex(MUTEX_ALL_ACCESS,FALSE,Mutex.Test)=NULL) if (hMutex = CreateMutex(NULL,FALSE,Mutex.Test )= NULL) coutCreate Mutex error!endl; return 0; for (i=0;iTHREAD_INSTANCE_NUMBER;i+) hi=CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)ThreadProc,(void*) ,信号量,信号量是维护0到指定最大值之间

17、的同步对象。 信号量状态在其计数大于0时是有信号的,而其计数是0时是无信号的。 信号量对象在控制上可以支持有限数量共享资源的访问。,信号量创建和撤销,创建信号量: HANDLE CreateSemaphore (PSECURITY_ATTRIBUTE psa,LONG lInitialCount, /开始时可供使用的资源数LONG lMaximumCount, /最大资源数 PCTSTR pszName); 撤销信号量: BOOL WINAPI ReleaseSemaphore(HANDLE hSemaphore,LONG lReleaseCount, /信号量的当前资源数增加 lReleas

18、eCountLPLONG lpPreviousCount);,信号量打开,打开信号量HANDLE OpenSemaphore (DWORD fdwAccess,BOOL bInherithandle,PCTSTR pszName);,#include stdafx.h #include #include #define THREAD_INSTANCE_NUMBER 3 #define PRODUCT_NUMBER 2 #define MAX_ITEMS 2 / 定义信号量 HANDLE m_S_Full; / Semaphore HANDLE m_S_Empty; / Semaphore HA

19、NDLE m_E_Mutex; / Event,int counter=0; void ThreadProducer(void *pData) int j; int ThreadNumTemp=(*(int *) pData); for (j=0;jPRODUCT_NUMBER;j+) WaitForSingleObject(m_S_Full, INFINITE); WaitForSingleObject(m_E_Mutex, INFINITE); / OK now, put product counter+; coutThreadProducer:ThreadNumTemp puts a p

20、orduct.endl; coutThreadProducer:ThreadNumTemp counter=counterendl; / relase comsumers semaphore ReleaseSemaphore(m_S_Empty, 1, NULL); / set event to signal SetEvent(m_E_Mutex); ,int main(int argc, char* argv) / 假设仓库最多容纳MAX_ITEMS个物品,开始仓库为空 DWORD IDPTHREAD_INSTANCE_NUMBER; DWORD IDCTHREAD_INSTANCE_NUMBER; HANDLE hpTHREAD_INSTANCE_NUMBER; HANDLE hcTHREAD_INSTANCE_NUMBER; int i; m_S_Full = CreateSemaphore(NULL, 0, MAX_ITEMS, NULL); /初始计数为M m_S_Empty = CreateSema

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论